[gen] New ajax system: more bugfixes.
This commit is contained in:
parent
d23b9be5e5
commit
40e3612682
|
@ -176,7 +176,7 @@ class Ref(Field):
|
||||||
<a target="appyIFrame"
|
<a target="appyIFrame"
|
||||||
var="tiedClassName=tiedClassName|ztool.getPortalType(field.klass);
|
var="tiedClassName=tiedClassName|ztool.getPortalType(field.klass);
|
||||||
className=ztool.getPortalType(obj.klass)"
|
className=ztool.getPortalType(obj.klass)"
|
||||||
href=":'%s/query?className=%s&search=%s:%s:%s&popup=1' % \
|
href=":'%s/query?className=%s&search=%s*%s*%s&popup=1' % \
|
||||||
(ztool.absolute_url(), tiedClassName, obj.uid, field.name, \
|
(ztool.absolute_url(), tiedClassName, obj.uid, field.name, \
|
||||||
popupMode)">
|
popupMode)">
|
||||||
<input type="button"
|
<input type="button"
|
||||||
|
@ -287,13 +287,13 @@ class Ref(Field):
|
||||||
<!-- Loop on every (tied or selectable) object -->
|
<!-- Loop on every (tied or selectable) object -->
|
||||||
<x for="tied in objects"
|
<x for="tied in objects"
|
||||||
var2="@currentNumber=currentNumber + 1;
|
var2="@currentNumber=currentNumber + 1;
|
||||||
rowCss=loop.tied.odd and 'even' or 'odd'">:obj.pxViewAsTied</x>
|
rowCss=loop.tied.odd and 'even' or 'odd'">:tied.pxViewAsTied</x>
|
||||||
</table>
|
</table>
|
||||||
<!-- Global actions -->
|
<!-- Global actions -->
|
||||||
<x if="mayEdit and checkboxes">:field.pxGlobalActions</x>
|
<x if="mayEdit and checkboxes">:field.pxGlobalActions</x>
|
||||||
<!-- (Bottom) navigation -->
|
<!-- (Bottom) navigation -->
|
||||||
<x>:tool.pxNavigate</x>
|
<x>:tool.pxNavigate</x>
|
||||||
<!-- Init checkboxes if present. -->
|
<!-- Init checkboxes if present -->
|
||||||
<script if="checkboxes">:'initCbs(%s)' % q(ajaxHookId)</script>
|
<script if="checkboxes">:'initCbs(%s)' % q(ajaxHookId)</script>
|
||||||
</div>''')
|
</div>''')
|
||||||
|
|
||||||
|
@ -437,8 +437,8 @@ class Ref(Field):
|
||||||
collapse=field.getCollapseInfo(obj, False);
|
collapse=field.getCollapseInfo(obj, False);
|
||||||
showSubTitles=req.get('showSubTitles', 'true') == 'true'">
|
showSubTitles=req.get('showSubTitles', 'true') == 'true'">
|
||||||
<!-- JS tables storing checkbox statuses if checkboxes are enabled -->
|
<!-- JS tables storing checkbox statuses if checkboxes are enabled -->
|
||||||
<script if="checkboxesEnabled and renderAll and (render == 'list')"
|
<script if="checkboxesEnabled and renderAll \
|
||||||
type="text/javascript">:field.getCbJsInit(zobj)</script>
|
and (render == 'list')">:field.getCbJsInit(zobj)</script>
|
||||||
<x if="linkList and renderAll and mayEdit"
|
<x if="linkList and renderAll and mayEdit"
|
||||||
var2="ajaxHookId='%s_%s_poss' % \
|
var2="ajaxHookId='%s_%s_poss' % \
|
||||||
(zobj.id, field.name)">:field.pxViewPickList</x>
|
(zobj.id, field.name)">:field.pxViewPickList</x>
|
||||||
|
@ -1265,7 +1265,7 @@ class Ref(Field):
|
||||||
code = "\nnode['_appy_%%s_cbs']={};\nnode['_appy_%%s_sem']='%s';" % \
|
code = "\nnode['_appy_%%s_cbs']={};\nnode['_appy_%%s_sem']='%s';" % \
|
||||||
default
|
default
|
||||||
poss = (self.link == 'list') and (code % ('poss', 'poss')) or ''
|
poss = (self.link == 'list') and (code % ('poss', 'poss')) or ''
|
||||||
return "var node=document.getElementById('%s_%s');%s%s" % \
|
return "var node=findNode(this, '%s_%s');%s%s" % \
|
||||||
(obj.id, self.name, code % ('objs', 'objs'), poss)
|
(obj.id, self.name, code % ('objs', 'objs'), poss)
|
||||||
|
|
||||||
def getAjaxData(self, hook, zobj, **params):
|
def getAjaxData(self, hook, zobj, **params):
|
||||||
|
|
|
@ -202,8 +202,8 @@ class UiSearch:
|
||||||
<td colspan=":len(columns)+1">:_('query_no_result')</td>
|
<td colspan=":len(columns)+1">:_('query_no_result')</td>
|
||||||
</tr>
|
</tr>
|
||||||
<x for="zobj in zobjects"
|
<x for="zobj in zobjects"
|
||||||
var2="@currentNumber=currentNumber + 1;
|
var2="rowCss=loop.zobj.odd and 'even' or 'odd';
|
||||||
rowCss=loop.zobj.odd and 'even' or 'odd'">:obj.pxViewAsResult</x>
|
@currentNumber=currentNumber + 1">:zobj.appy().pxViewAsResult</x>
|
||||||
</table>
|
</table>
|
||||||
<!-- The button for selecting objects and closing the popup -->
|
<!-- The button for selecting objects and closing the popup -->
|
||||||
<div if="inPopup and cbShown" align=":dleft">
|
<div if="inPopup and cbShown" align=":dleft">
|
||||||
|
@ -241,7 +241,7 @@ class UiSearch:
|
||||||
<div var="ajaxHookId='queryResult';
|
<div var="ajaxHookId='queryResult';
|
||||||
className=req['className'];
|
className=req['className'];
|
||||||
searchName=req.get('search', '');
|
searchName=req.get('search', '');
|
||||||
uiSearch=uiSearch|ztool.getSearch(className,searchName,ui=True);
|
uiSearch=field|ztool.getSearch(className, searchName, ui=True);
|
||||||
rootHookId=uiSearch.getRootHookId();
|
rootHookId=uiSearch.getRootHookId();
|
||||||
refInfo=ztool.getRefInfo();
|
refInfo=ztool.getRefInfo();
|
||||||
refObject=refInfo[0];
|
refObject=refInfo[0];
|
||||||
|
@ -389,7 +389,7 @@ class UiSearch:
|
||||||
'''Returns the code that creates JS data structures for storing the
|
'''Returns the code that creates JS data structures for storing the
|
||||||
status of checkboxes for every result of this search.'''
|
status of checkboxes for every result of this search.'''
|
||||||
default = self.search.checkboxesDefault and 'unchecked' or 'checked'
|
default = self.search.checkboxesDefault and 'unchecked' or 'checked'
|
||||||
return '''var node=document.getElementById('%s');
|
return '''var node=findNode(this, '%s');
|
||||||
node['_appy_objs_cbs'] = {};
|
node['_appy_objs_cbs'] = {};
|
||||||
node['_appy_objs_sem'] = '%s';''' % (hookId, default)
|
node['_appy_objs_sem'] = '%s';''' % (hookId, default)
|
||||||
|
|
||||||
|
|
|
@ -223,11 +223,11 @@ class ToolMixin(BaseMixin):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getRootClasses(self):
|
def getRootClasses(self):
|
||||||
'''Returns the list of root classes for this application.'''
|
'''Returns the list of root classes for this application'''
|
||||||
cfg = self.getProductConfig().appConfig
|
cfg = self.getProductConfig().appConfig
|
||||||
rootClasses = cfg.rootClasses
|
rootClasses = cfg.rootClasses
|
||||||
if not rootClasses:
|
if not rootClasses:
|
||||||
# We consider every class as being a root class.
|
# We consider every class as being a root class
|
||||||
rootClasses = self.getProductConfig().appClassNames
|
rootClasses = self.getProductConfig().appClassNames
|
||||||
return [self.getAppyClass(k) for k in rootClasses]
|
return [self.getAppyClass(k) for k in rootClasses]
|
||||||
|
|
||||||
|
@ -749,10 +749,10 @@ class ToolMixin(BaseMixin):
|
||||||
# It is a custom search whose parameters are in the session
|
# It is a custom search whose parameters are in the session
|
||||||
fields = self.REQUEST.SESSION['searchCriteria']
|
fields = self.REQUEST.SESSION['searchCriteria']
|
||||||
res = Search('customSearch', **fields)
|
res = Search('customSearch', **fields)
|
||||||
elif ':' in name:
|
elif '*' in name:
|
||||||
# The search is defined in a Ref field with link=popup. Get the
|
# The search is defined in a Ref field with link=popup. Get the
|
||||||
# search, the initiator object and the Ref field.
|
# search, the initiator object and the Ref field.
|
||||||
uid, ref, mode = name.split(':')
|
uid, ref, mode = name.split('*')
|
||||||
initiator = self.getObject(uid, appy=True)
|
initiator = self.getObject(uid, appy=True)
|
||||||
initiatorField = initiator.getField(ref)
|
initiatorField = initiator.getField(ref)
|
||||||
res = getattr(initiator.klass, ref).select
|
res = getattr(initiator.klass, ref).select
|
||||||
|
|
|
@ -405,8 +405,8 @@ class BaseMixin:
|
||||||
pageInfo = phaseObj.getPageInfo(rq['page'], 'view')
|
pageInfo = phaseObj.getPageInfo(rq['page'], 'view')
|
||||||
if not pageInfo: urlBack = tool.getHomePage()
|
if not pageInfo: urlBack = tool.getHomePage()
|
||||||
else: urlBack = self.getUrl(page=pageInfo.page.name)
|
else: urlBack = self.getUrl(page=pageInfo.page.name)
|
||||||
self.say(self.translate('object_canceled'))
|
|
||||||
self.removeLock(rq['page'])
|
self.removeLock(rq['page'])
|
||||||
|
self.say(self.translate('object_canceled'))
|
||||||
if inPopup: return back
|
if inPopup: return back
|
||||||
return self.goto(urlBack)
|
return self.goto(urlBack)
|
||||||
|
|
||||||
|
|
|
@ -403,7 +403,7 @@ function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
|
||||||
else hidden.value = 'False';
|
else hidden.value = 'False';
|
||||||
}
|
}
|
||||||
|
|
||||||
// JS implementation of Python ''.rsplit.
|
// JS implementation of Python ''.rsplit
|
||||||
function _rsplit(s, delimiter, limit) {
|
function _rsplit(s, delimiter, limit) {
|
||||||
var elems = s.split(delimiter);
|
var elems = s.split(delimiter);
|
||||||
var exc = elems.length - limit;
|
var exc = elems.length - limit;
|
||||||
|
@ -419,11 +419,11 @@ function _rsplit(s, delimiter, limit) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (Un)checks a checkbox corresponding to a linked object.
|
// (Un)checks a checkbox corresponding to a linked object
|
||||||
function toggleCb(checkbox) {
|
function toggleCb(checkbox) {
|
||||||
var name = checkbox.getAttribute('name');
|
var name = checkbox.getAttribute('name');
|
||||||
var elems = _rsplit(name, '_', 3);
|
var elems = _rsplit(name, '_', 3);
|
||||||
// Get the DOM node corresponding to the Ref field.
|
// Get the DOM node corresponding to the Ref field
|
||||||
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
||||||
// Get the array that stores checkbox statuses.
|
// Get the array that stores checkbox statuses.
|
||||||
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
||||||
|
@ -440,17 +440,26 @@ function toggleCb(checkbox) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise checkboxes of a Ref field or Search.
|
function findNode(node, id) {
|
||||||
|
/* When coming back from the iframe popup, we are still in the context of the
|
||||||
|
iframe, which can cause problems for finding nodes. We have found that this
|
||||||
|
case can be detected by checking node.window. */
|
||||||
|
if (node.window) var container = node.window.document;
|
||||||
|
else var container = window.parent.document;
|
||||||
|
return container.getElementById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise checkboxes of a Ref field or Search
|
||||||
function initCbs(id) {
|
function initCbs(id) {
|
||||||
var elems = _rsplit(id, '_', 3);
|
var elems = _rsplit(id, '_', 3);
|
||||||
// Get the DOM node corresponding to the Ref field.
|
// Get the DOM node corresponding to the Ref field
|
||||||
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
||||||
// Get the array that stores checkbox statuses.
|
// Get the array that stores checkbox statuses
|
||||||
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
||||||
// Get the array semantics
|
// Get the array semantics
|
||||||
var semantics = node['_appy_' + elems[2] + '_sem'];
|
var semantics = node['_appy_' + elems[2] + '_sem'];
|
||||||
var value = (semantics == 'unchecked')? false: true;
|
var value = (semantics == 'unchecked')? false: true;
|
||||||
// Update visible checkboxes.
|
// Update visible checkboxes
|
||||||
var checkboxes = getElementsHavingName('input', id);
|
var checkboxes = getElementsHavingName('input', id);
|
||||||
for (var i=0; i < checkboxes.length; i++) {
|
for (var i=0; i < checkboxes.length; i++) {
|
||||||
if (checkboxes[i].value in statuses) checkboxes[i].checked = value;
|
if (checkboxes[i].value in statuses) checkboxes[i].checked = value;
|
||||||
|
@ -458,15 +467,15 @@ function initCbs(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle all checkboxes of a Ref field or Search.
|
// Toggle all checkboxes of a Ref field or Search
|
||||||
function toggleAllCbs(id) {
|
function toggleAllCbs(id) {
|
||||||
var elems = _rsplit(id, '_', 3);
|
var elems = _rsplit(id, '_', 3);
|
||||||
// Get the DOM node corresponding to the Ref field.
|
// Get the DOM node corresponding to the Ref field
|
||||||
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
var node = document.getElementById(elems[0] + '_' + elems[1]);
|
||||||
// Empty the array that stores checkbox statuses.
|
// Empty the array that stores checkbox statuses
|
||||||
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
var statuses = node['_appy_' + elems[2] + '_cbs'];
|
||||||
for (var key in statuses) delete statuses[key];
|
for (var key in statuses) delete statuses[key];
|
||||||
// Switch the array semantics.
|
// Switch the array semantics
|
||||||
var semAttr = '_appy_' + elems[2] + '_sem';
|
var semAttr = '_appy_' + elems[2] + '_sem';
|
||||||
if (node[semAttr] == 'unchecked') node[semAttr] = 'checked';
|
if (node[semAttr] == 'unchecked') node[semAttr] = 'checked';
|
||||||
else node[semAttr] = 'unchecked';
|
else node[semAttr] = 'unchecked';
|
||||||
|
@ -892,7 +901,7 @@ function closePopup(popupId, clean) {
|
||||||
// Reinitialise the enclosing iframe
|
// Reinitialise the enclosing iframe
|
||||||
var iframe = container.getElementById('appyIFrame');
|
var iframe = container.getElementById('appyIFrame');
|
||||||
iframe.style.width = null;
|
iframe.style.width = null;
|
||||||
iframe.innerHTML = '';
|
while (iframe.firstChild) iframe.removeChild(iframe.firstChild);
|
||||||
// Leave the form silently if we are on an edit page
|
// Leave the form silently if we are on an edit page
|
||||||
iframe.contentWindow.onbeforeunload = null;
|
iframe.contentWindow.onbeforeunload = null;
|
||||||
}
|
}
|
||||||
|
@ -907,10 +916,10 @@ function backFromPopup() {
|
||||||
|
|
||||||
function showAppyMessage(message) {
|
function showAppyMessage(message) {
|
||||||
// Fill the message zone with the message to display
|
// Fill the message zone with the message to display
|
||||||
var messageZone = document.getElementById('appyMessageContent');
|
var messageZone = getAjaxHook(':appyMessageContent');
|
||||||
messageZone.innerHTML = message;
|
messageZone.innerHTML = message;
|
||||||
// Display the message zone
|
// Display the message zone
|
||||||
var messageDiv = document.getElementById('appyMessage');
|
var messageDiv = getAjaxHook(':appyMessage');
|
||||||
messageDiv.style.display = 'block';
|
messageDiv.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,12 +1181,12 @@ function onSelectObjects(nodeId, objectUrl, mode, sortKey, sortOrder,
|
||||||
var node = document.getElementById(nodeId);
|
var node = document.getElementById(nodeId);
|
||||||
var uids = stringFromDictKeys(node['_appy_objs_cbs']);
|
var uids = stringFromDictKeys(node['_appy_objs_cbs']);
|
||||||
var semantics = node['_appy_objs_sem'];
|
var semantics = node['_appy_objs_sem'];
|
||||||
// Show an error message if no element is selected.
|
// Show an error message if no element is selected
|
||||||
if ((semantics == 'checked') && (!uids)) {
|
if ((semantics == 'checked') && (!uids)) {
|
||||||
openPopup('alertPopup', no_elem_selected);
|
openPopup('alertPopup', no_elem_selected);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Close the popup.
|
// Close the popup
|
||||||
closePopup('iframePopup');
|
closePopup('iframePopup');
|
||||||
/* When refreshing the Ref field we will need to pass all those parameters,
|
/* When refreshing the Ref field we will need to pass all those parameters,
|
||||||
for replaying the popup query. */
|
for replaying the popup query. */
|
||||||
|
@ -1190,7 +1199,7 @@ function onSelectObjects(nodeId, objectUrl, mode, sortKey, sortOrder,
|
||||||
askField(':'+nodeId, objectUrl, 'edit', params, false);
|
askField(':'+nodeId, objectUrl, 'edit', params, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Link the selected objects and refresh the Ref view widget.
|
// Link the selected objects and refresh the Ref view widget
|
||||||
params['action'] = 'onSelectFromPopup';
|
params['action'] = 'onSelectFromPopup';
|
||||||
askField(':'+nodeId, objectUrl, 'view', params, false);
|
askField(':'+nodeId, objectUrl, 'view', params, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,7 +279,7 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<!-- The message content -->
|
<!-- The message content -->
|
||||||
<div id="appyMessageContent"></div>
|
<div id="appyMessageContent"></div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" var="messages=ztool.consumeMessages()"
|
<script var="messages=ztool.consumeMessages()"
|
||||||
if="messages">::'showAppyMessage(%s)' % q(messages)</script>''')
|
if="messages">::'showAppyMessage(%s)' % q(messages)</script>''')
|
||||||
|
|
||||||
# The page footer
|
# The page footer
|
||||||
|
|
|
@ -728,12 +728,16 @@ class AbstractWrapper(object):
|
||||||
x=resp.setHeader('Content-Language', lang);
|
x=resp.setHeader('Content-Language', lang);
|
||||||
x=resp.setHeader('Cache-Control', 'no-cache')">
|
x=resp.setHeader('Cache-Control', 'no-cache')">
|
||||||
|
|
||||||
<!-- If an action is defined, execute it on p_zobj or on p_field. -->
|
<!-- If an action is defined, execute it on p_zobj or on p_field -->
|
||||||
<x if="action"
|
<x if="action"
|
||||||
var2="msg=ztool.executeAjaxAction(action, obj, field) or '';
|
var2="msg=ztool.executeAjaxAction(action, obj, field) or '';
|
||||||
x=resp.setHeader('Appy-Message', msg)"></x>
|
x=resp.setHeader('Appy-Message', msg)"></x>
|
||||||
|
|
||||||
<!-- Then, call the PX on p_obj or on p_field. -->
|
<!-- Consume and return any session message -->
|
||||||
|
<x var="msg=ztool.consumeMessages()" if="msg"
|
||||||
|
var2="x=resp.setHeader('Appy-Message', msg)"></x>
|
||||||
|
|
||||||
|
<!-- Then, call the PX on p_obj or on p_field -->
|
||||||
<x if="not field">:getattr(obj, px[0])</x>
|
<x if="not field">:getattr(obj, px[0])</x>
|
||||||
<x if="field">:getattr(field, px[-1])</x>
|
<x if="field">:getattr(field, px[-1])</x>
|
||||||
</x>''')
|
</x>''')
|
||||||
|
|
Loading…
Reference in a new issue