[gen] FInalized ajaxification of search rows and rows of tied objects in Refs.
This commit is contained in:
parent
f44bb4e06b
commit
a6645f33ff
|
@ -115,10 +115,12 @@ class Ref(Field):
|
|||
<img src=":url('edit')" title=":_('object_edit')"/>
|
||||
</a>
|
||||
<!-- Delete -->
|
||||
<img var="mayDeleteViaField=inPickList and True or field.delete"
|
||||
<img var="mayDeleteViaField=inPickList and True or field.delete;
|
||||
back=(inMenu and (layoutType=='buttons')) and \
|
||||
q(zobj.id) or 'null'"
|
||||
if="mayEdit and mayDeleteViaField and tied.o.mayDelete()"
|
||||
class="clickable" title=":_('object_delete')" src=":url('delete')"
|
||||
onclick=":'onDeleteObject(%s)' % q(tiedUid)"/>
|
||||
onclick=":'onDeleteObject(%s,%s)' % (q(tiedUid), back)"/>
|
||||
<!-- Unlink -->
|
||||
<img if="mayUnlink and field.mayUnlinkElement(obj, tied)"
|
||||
var2="imgName=linkList and 'unlinkUp' or 'unlink'; action='unlink'"
|
||||
|
@ -313,7 +315,8 @@ class Ref(Field):
|
|||
batchNumber=len(objects);
|
||||
tiedClassName=tiedClassName|ztool.getPortalType(field.klass);
|
||||
tiedClassLabel=tiedClassLabel|_(tiedClassName);
|
||||
target=ztool.getLinksTargetInfo(field.klass);
|
||||
backHook=(layoutType == 'cell') and zobj.id or None;
|
||||
target=ztool.getLinksTargetInfo(field.klass, backHook);
|
||||
mayEdit=mayEdit|\
|
||||
not field.isBack and zobj.mayEdit(field.writePermission);
|
||||
mayAdd=False;
|
||||
|
@ -411,7 +414,8 @@ class Ref(Field):
|
|||
folder=zobj.getCreateFolder();
|
||||
tiedClassName=ztool.getPortalType(field.klass);
|
||||
tiedClassLabel=_(tiedClassName);
|
||||
target=ztool.getLinksTargetInfo(field.klass);
|
||||
backHook=(layoutType == 'cell') and zobj.id or None;
|
||||
target=ztool.getLinksTargetInfo(field.klass, backHook);
|
||||
mayEdit=not field.isBack and zobj.mayEdit(field.writePermission);
|
||||
mayAdd=mayEdit and field.mayAdd(zobj, checkMayEdit=False);
|
||||
mayLink=mayEdit and field.mayAdd(zobj, mode='link', \
|
||||
|
@ -1274,7 +1278,7 @@ class Ref(Field):
|
|||
params = sutils.getStringDict(params)
|
||||
px = hook.endswith('_poss') and 'pxViewPickList' or 'pxView'
|
||||
px = '%s:%s' % (self.name, px)
|
||||
return "document.getElementById('%s')['ajax']=new AjaxData('%s', " \
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'%s', %s, null, '%s')" % \
|
||||
(hook, hook, px, params, zobj.absolute_url())
|
||||
|
||||
|
@ -1282,7 +1286,7 @@ class Ref(Field):
|
|||
'''Initializes an AjaxData object on the DOM node corresponding to
|
||||
p_hook = a row within the list of referred objects.'''
|
||||
hook = obj.id
|
||||
return "document.getElementById('%s')['ajax']=new AjaxData('%s', " \
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'pxViewAsTiedFromAjax',%s,'%s','%s')" % \
|
||||
(hook, hook, sutils.getStringDict(params), parentHook, obj.url)
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ class UiSearch:
|
|||
params['className'] = self.className
|
||||
params['searchName'] = self.name
|
||||
params = sutils.getStringDict(params)
|
||||
return "document.getElementById('%s')['ajax']=new AjaxData('%s', " \
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'pxResult', %s, null, '%s')" % \
|
||||
(hook, hook, params, ztool.absolute_url())
|
||||
|
||||
|
@ -408,7 +408,7 @@ class UiSearch:
|
|||
'''Initializes an AjaxData object on the DOM node corresponding to
|
||||
p_hook = a row within the list of results.'''
|
||||
hook = zobj.id
|
||||
return "document.getElementById('%s')['ajax']=new AjaxData('%s', " \
|
||||
return "getAjaxHook('%s',true)['ajax']=new AjaxData('%s', " \
|
||||
"'pxViewAsResultFromAjax',%s,'%s','%s')" % \
|
||||
(hook, hook, sutils.getStringDict(params), parentHook,
|
||||
zobj.absolute_url())
|
||||
|
|
|
@ -1242,13 +1242,13 @@ class ToolMixin(BaseMixin):
|
|||
if len(label) < 15: return 'buttonFixed button'
|
||||
return 'button'
|
||||
|
||||
def getLinksTargetInfo(self, klass):
|
||||
def getLinksTargetInfo(self, klass, back=None):
|
||||
'''Appy allows to open links to view or edit instances of p_klass
|
||||
either via the same browser window, or via a popup. This method
|
||||
returns info about that, as an object having 2 attributes:
|
||||
- target is "_self" if the link leads to the same browser window,
|
||||
"appyIFrame" if the link must be opened in a popup;
|
||||
- openPopup is unused if target is "_self" and contains the
|
||||
- openPopup is unused if target is "_self" or contains the
|
||||
Javascript code to open the popup.'''
|
||||
res = Object(target='_self', openPopup='')
|
||||
if hasattr(klass, 'popup'):
|
||||
|
@ -1256,10 +1256,14 @@ class ToolMixin(BaseMixin):
|
|||
d = klass.popup
|
||||
if isinstance(d, basestring):
|
||||
# Width only
|
||||
params = int(d[:-2])
|
||||
params = d[:-2]
|
||||
else:
|
||||
# Width and height
|
||||
params = "%s, %s" % (d[0][:-2], d[1][:-2])
|
||||
# If "back" is specified, it corresponds to some tag on the main
|
||||
# page, that must be ajax-refreshed when coming back from the popup.
|
||||
# Else, when back, the entire page will be reloaded.
|
||||
if back: params += ", '%s'" % back
|
||||
res.openPopup = "openPopup('iframePopup',null,%s)" % params
|
||||
return res
|
||||
|
||||
|
|
|
@ -151,17 +151,22 @@ class BaseMixin:
|
|||
self.getParentNode().manage_delObjects([self.id])
|
||||
|
||||
def onDelete(self):
|
||||
'''Called when an object deletion is triggered from the ui.'''
|
||||
'''Called when an object deletion is triggered from the ui'''
|
||||
rq = self.REQUEST
|
||||
self.delete()
|
||||
if self.getUrl(rq['HTTP_REFERER'],mode='raw') ==self.getUrl(mode='raw'):
|
||||
tool = self.getTool()
|
||||
obj = tool.getObject(rq['uid'])
|
||||
obj.delete()
|
||||
msg = obj.translate('action_done')
|
||||
# If we are called from an Ajax request, simply return msg
|
||||
if hasattr(rq, 'pxContext') and rq.pxContext['ajax']: return msg
|
||||
if obj.getUrl(rq['HTTP_REFERER'], mode='raw') == obj.getUrl(mode='raw'):
|
||||
# We were consulting the object that has been deleted. Go back to
|
||||
# the main page.
|
||||
urlBack = self.getTool().getSiteUrl()
|
||||
urlBack = tool.getSiteUrl()
|
||||
else:
|
||||
urlBack = self.getUrl(rq['HTTP_REFERER'])
|
||||
self.say(self.translate('action_done'))
|
||||
self.goto(urlBack)
|
||||
urlBack = obj.getUrl(rq['HTTP_REFERER'])
|
||||
obj.say(msg)
|
||||
obj.goto(urlBack)
|
||||
|
||||
def onDeleteEvent(self):
|
||||
'''Called when an event (from object history) deletion is triggered
|
||||
|
@ -395,7 +400,7 @@ class BaseMixin:
|
|||
else:
|
||||
if isNew: urlBack = tool.getHomePage() # Go back to home page
|
||||
else:
|
||||
# Return to the same page, excepted if unshowable on view.
|
||||
# Return to the same page, excepted if unshowable on view
|
||||
phaseObj = self.getAppyPhases(True, 'view')
|
||||
pageInfo = phaseObj.getPageInfo(rq['page'], 'view')
|
||||
if not pageInfo: urlBack = tool.getHomePage()
|
||||
|
|
|
@ -90,10 +90,18 @@ function evalInnerScripts(xhrObject, hookElem) {
|
|||
for (var i=0; i<scripts.length; i++) { eval(scripts[i].innerHTML) }
|
||||
}
|
||||
|
||||
function injectChunk(elem, content){
|
||||
if (!isIe) elem.innerHTML = content;
|
||||
function injectChunk(elem, content, inner, searchTop){
|
||||
var res = elem;
|
||||
if (!isIe || (elem.tagName != 'TABLE')) {
|
||||
if (inner) res.innerHTML = content;
|
||||
else {
|
||||
if (elem.tagName != 'TABLE') elem.innerHTML = content;
|
||||
// Replace p_elem with a new node filled with p_content and return it
|
||||
var id = elem.id;
|
||||
if (searchTop) id = ':' + id;
|
||||
elem.outerHTML = content;
|
||||
res = getAjaxHook(id); // Get the new element
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* IE doesn't want to replace content of a table. Force it to do so via
|
||||
a temporary DOM element. */
|
||||
|
@ -102,14 +110,15 @@ function injectChunk(elem, content){
|
|||
temp.firstChild.id = elem.id;
|
||||
elem.parentNode.replaceChild(temp.firstChild, elem);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function getAjaxHook(hookId) {
|
||||
function getAjaxHook(hookId, forceTop) {
|
||||
/* Gets the XHTML element whose ID is p_hookId: it will be the placeholder
|
||||
for the result of an ajax request. If p_hookId starts with ':', we search
|
||||
the element in the top browser window, not in the current one that can be
|
||||
an iframe.*/
|
||||
an iframe. If p_forceTop is true, even if hookId does not start with ':',
|
||||
if the elem is not found we will search in the top browser window. */
|
||||
if (!hookId) return;
|
||||
var container = window.document;
|
||||
var startIndex = 0;
|
||||
|
@ -117,7 +126,10 @@ function getAjaxHook(hookId) {
|
|||
container = window.top.document;
|
||||
startIndex = 1;
|
||||
}
|
||||
return container.getElementById(hookId.slice(startIndex));
|
||||
var id = hookId.slice(startIndex);
|
||||
var res = container.getElementById(id);
|
||||
if (!res && forceTop) res = window.top.document.getElementById(id);
|
||||
return res;
|
||||
}
|
||||
|
||||
function getAjaxChunk(pos) {
|
||||
|
@ -131,21 +143,18 @@ function getAjaxChunk(pos) {
|
|||
// The request has been initialized: display the waiting radar
|
||||
var hookElem = getAjaxHook(hook);
|
||||
if (hookElem)
|
||||
injectChunk(hookElem, "<div align=\"center\"><img src=\"ui/waiting.gif\"/><\/div>");
|
||||
injectChunk(hookElem, "<div align=\"center\"><img src=\"ui/waiting.gif\"/><\/div>", true);
|
||||
}
|
||||
if (xhrObjects[pos].xhr.readyState == 4) {
|
||||
// We have received the HTML chunk
|
||||
var hookElem = getAjaxHook(hook);
|
||||
if (hookElem) {
|
||||
injectChunk(hookElem, xhrObjects[pos].xhr.responseText);
|
||||
var content = xhrObjects[pos].xhr.responseText;
|
||||
var searchTop = hook[0] == ':';
|
||||
var injected = injectChunk(hookElem, content, false, searchTop);
|
||||
// Call a custom Javascript function if required
|
||||
if (xhrObjects[pos].onGet) {
|
||||
xhrObjects[pos].onGet(xhrObjects[pos], hookElem);
|
||||
}
|
||||
// Eval inner scripts if any
|
||||
var innerScripts = getElementsHavingName('div', 'appyHook');
|
||||
for (var i=0; i<innerScripts.length; i++) {
|
||||
eval(innerScripts[i].innerHTML);
|
||||
xhrObjects[pos].onGet(xhrObjects[pos], injected);
|
||||
}
|
||||
// Display the Appy message if present
|
||||
var msg = xhrObjects[pos].xhr.getResponseHeader('Appy-Message');
|
||||
|
@ -245,10 +254,12 @@ function AjaxData(hook, px, params, parentHook, url, mode, beforeSend, onGet) {
|
|||
function askAjax(hook, form, params) {
|
||||
/* Call askAjaxChunk by getting an AjaxData instance from p_hook, a
|
||||
potential action from p_form and additional parameters from p_param. */
|
||||
var d = document.getElementById(hook)['ajax'];
|
||||
var d = getAjaxHook(hook)['ajax'];
|
||||
// Complete data with a parent data if present
|
||||
if (d['parentHook']) {
|
||||
var parent = document.getElementById(d['parentHook'])['ajax'];
|
||||
var parentHook = d['parentHook'];
|
||||
if (hook[0] == ':') parentHook = ':' + parentHook;
|
||||
var parent = getAjaxHook(parentHook)['ajax'];
|
||||
for (var key in parent) {
|
||||
if (key == 'params') continue; // Will get a specific treatment herafter
|
||||
if (!d[key]) d[key] = parent[key]; // Override if no value on child
|
||||
|
@ -278,7 +289,9 @@ function askAjax(hook, form, params) {
|
|||
else var mode = d.mode;
|
||||
// Get p_params if given. Note that they override anything else.
|
||||
if (params) { for (var key in params) d.params[key] = params[key]; }
|
||||
askAjaxChunk(d.hook,mode,d.url,d.px,d.params,d.beforeSend,d.onGet) }
|
||||
askAjaxChunk(hook, mode, d.url, d.px, d.params, d.beforeSend,
|
||||
evalInnerScripts);
|
||||
}
|
||||
|
||||
/* The functions below wrap askAjaxChunk for getting specific content through
|
||||
an Ajax request. */
|
||||
|
@ -658,10 +671,10 @@ function triggerTransition(formId, transitionId, msg, back) {
|
|||
submitForm(formId, msg, true, back);
|
||||
}
|
||||
|
||||
function onDeleteObject(objectUid) {
|
||||
f = document.getElementById('deleteForm');
|
||||
f.objectUid.value = objectUid;
|
||||
askConfirm('form', 'deleteForm', action_confirm);
|
||||
function onDeleteObject(uid, back) {
|
||||
var f = document.getElementById('deleteForm');
|
||||
f.uid.value = uid;
|
||||
submitForm('deleteForm', action_confirm, false, back);
|
||||
}
|
||||
|
||||
function onDeleteEvent(objectUid, eventTime) {
|
||||
|
@ -829,7 +842,7 @@ function protectAppyForm() {
|
|||
}
|
||||
|
||||
// Functions for opening and closing a popup
|
||||
function openPopup(popupId, msg, width, height) {
|
||||
function openPopup(popupId, msg, width, height, back) {
|
||||
// Put the message into the popup
|
||||
if (msg) {
|
||||
var msgHook = (popupId == 'alertPopup')? 'appyAlertText': 'appyConfirmText';
|
||||
|
@ -844,7 +857,7 @@ function openPopup(popupId, msg, width, height) {
|
|||
if (width) popup.style.width = width + 'px';
|
||||
if (height) popup.style.height = height + 'px';
|
||||
if (popupId == 'iframePopup') {
|
||||
// Initialize iframe's width.
|
||||
// Initialize iframe's width
|
||||
var iframe = document.getElementById('appyIFrame');
|
||||
if (!width) width = window.innerWidth - 200;
|
||||
if (!height) {
|
||||
|
@ -856,6 +869,7 @@ function openPopup(popupId, msg, width, height) {
|
|||
iframe.style.width = (width-20) + 'px';
|
||||
popup.style.height = height + 'px';
|
||||
iframe.style.height = (height-20) + 'px';
|
||||
popup['back'] = back;
|
||||
}
|
||||
popup.style.display = 'block';
|
||||
}
|
||||
|
@ -882,11 +896,13 @@ function closePopup(popupId, clean) {
|
|||
// Leave the form silently if we are on an edit page
|
||||
iframe.contentWindow.onbeforeunload = null;
|
||||
}
|
||||
return popup;
|
||||
}
|
||||
|
||||
function backFromPopup() {
|
||||
closePopup('iframePopup');
|
||||
window.parent.location = window.parent.location;
|
||||
var popup = closePopup('iframePopup');
|
||||
if (popup['back']) askAjax(':'+popup['back']);
|
||||
else window.parent.location = window.parent.location;
|
||||
}
|
||||
|
||||
function showAppyMessage(message) {
|
||||
|
|
|
@ -106,9 +106,8 @@ class ToolWrapper(AbstractWrapper):
|
|||
<script>::ztool.getJavascriptMessages()</script>
|
||||
|
||||
<!-- Global form for deleting an object -->
|
||||
<form id="deleteForm" method="post" action="do">
|
||||
<input type="hidden" name="action" value="Delete"/>
|
||||
<input type="hidden" name="objectUid"/>
|
||||
<form id="deleteForm" method="post" action=":'%s/onDelete' % tool.url">
|
||||
<input type="hidden" name="uid"/>
|
||||
</form>
|
||||
<!-- Global form for deleting an event from an object's history -->
|
||||
<form id="deleteEventForm" method="post" action="do">
|
||||
|
@ -133,7 +132,7 @@ class ToolWrapper(AbstractWrapper):
|
|||
</form>
|
||||
<!-- Global form for generating/freezing a document from a pod template -->
|
||||
<form id="podForm" name="podForm" method="post"
|
||||
action=":ztool.absolute_url() + '/doPod'">
|
||||
action=":'%s/doPod' % tool.url">
|
||||
<input type="hidden" name="objectUid"/>
|
||||
<input type="hidden" name="fieldName"/>
|
||||
<input type="hidden" name="template"/>
|
||||
|
|
|
@ -602,13 +602,14 @@ class AbstractWrapper(object):
|
|||
tied=obj;
|
||||
zobj=ztool.getObject(sourceId);
|
||||
obj=zobj.appy();
|
||||
inMenu=False;
|
||||
field=zobj.getAppyType(refFieldName);
|
||||
layoutType='view';
|
||||
render=field.getRenderMode(layoutType);
|
||||
linkList=field.link == 'list';
|
||||
numberWidth=len(str(totalNumber));
|
||||
tiedClassName=ztool.getPortalType(field.klass);
|
||||
target=ztool.getLinksTargetInfo(field.klass);
|
||||
target=ztool.getLinksTargetInfo(field.klass, zobj.id);
|
||||
mayEdit=not field.isBack and zobj.mayEdit(field.writePermission);
|
||||
mayLink=not inPickList and mayEdit and \
|
||||
field.mayAdd(zobj, mode='link', checkMayEdit=False);
|
||||
|
|
Loading…
Reference in a new issue