--- a/web/data/cubicweb.ajax.js Tue Dec 22 09:38:08 2009 +0100
+++ b/web/data/cubicweb.ajax.js Tue Dec 22 11:07:07 2009 +0100
@@ -13,54 +13,80 @@
var loaded = [];
var jqtagfilter = tag + '[' + srcattr + ']';
jQuery('head ' + jqtagfilter).each(function(i) {
- loaded.push(this.getAttribute(srcattr));
+ loaded.push(this.getAttribute(srcattr));
});
node.find(tag).each(function(i) {
- if (this.getAttribute(srcattr)) {
- if (!loaded.contains(this.getAttribute(srcattr))) {
- jQuery(this).appendTo(head);
- }
- } else {
- jQuery(this).appendTo(head);
- }
+ if (this.getAttribute(srcattr)) {
+ if (!loaded.contains(this.getAttribute(srcattr))) {
+ jQuery(this).appendTo(head);
+ }
+ } else {
+ jQuery(this).appendTo(head);
+ }
});
node.find(jqtagfilter).remove();
}
/*
- * inspect dom response, search for a <div class="ajaxHtmlHead"> node and
- * put its content into the real document's head.
+ * inspect dom response (as returned by getDomFromResponse), search for
+ * a <div class="ajaxHtmlHead"> node and put its content into the real
+ * document's head.
* This enables dynamic css and js loading and is used by replacePageChunk
*/
-function loadAjaxHtmlHead(node) {
- var head = jQuery('head');
- node = jQuery(node).find('div.ajaxHtmlHead');
- _loadAjaxHtmlHead(node, head, 'script', 'src');
- _loadAjaxHtmlHead(node, head, 'link', 'href');
- node.find('*').appendTo(head);
+function loadAjaxHtmlHead(response) {
+ var $head = jQuery('head');
+ var $responseHead = jQuery(response).find('div.ajaxHtmlHead');
+ // no ajaxHtmlHead found, no processing required
+ if (!$responseHead.length) {
+ return response;
+ }
+ _loadAjaxHtmlHead($responseHead, $head, 'script', 'src');
+ _loadAjaxHtmlHead($responseHead, $head, 'link', 'href');
+ // add any remaining children (e.g. meta)
+ $responseHead.children().appendTo($head);
+ // remove original container, which is now empty
+ $responseHead.remove();
+ // if there was only one actual node in the reponse besides
+ // the ajaxHtmlHead, then remove the wrapper created by
+ // getDomFromResponse() and return this single element
+ // For instance :
+ // 1/ CW returned the following content :
+ // <div>the-actual-content</div><div class="ajaxHtmlHead">...</div>
+ // 2/ getDomFromReponse() wrapped this into a single DIV to hold everything
+ // in one, unique, dom element
+ // 3/ now that we've removed the ajaxHtmlHead div, the only
+ // node left in the wrapper if the 'real' node built by the view,
+ // we can safely return this node. Otherwise, the view itself
+ // returned several 'root' nodes and we need to keep the wrapper
+ // created by getDomFromResponse()
+ if (response.childNodes.length == 1 &&
+ response.getAttribute('cubicweb:type') == 'cwResponseWrapper') {
+ return response.firstChild;
+ }
+ return response;
}
function preprocessAjaxLoad(node, newdomnode) {
- loadAjaxHtmlHead(newdomnode);
+ return loadAjaxHtmlHead(newdomnode);
}
function postAjaxLoad(node) {
// find sortable tables if there are some
if (typeof(Sortable) != 'undefined') {
- Sortable.sortTables(node);
+ Sortable.sortTables(node);
}
// find textareas and wrap them if there are some
if (typeof(FCKeditor) != 'undefined') {
- buildWysiwygEditors();
+ buildWysiwygEditors();
}
if (typeof initFacetBoxEvents != 'undefined') {
- initFacetBoxEvents(node);
+ initFacetBoxEvents(node);
}
if (typeof buildWidgets != 'undefined') {
- buildWidgets(node);
+ buildWidgets(node);
}
if (typeof roundedCorners != 'undefined') {
- roundedCorners(node);
+ roundedCorners(node);
}
if (typeof setFormsTarget != 'undefined') {
setFormsTarget(node);
@@ -71,7 +97,7 @@
// we probably need to unbind the fired events
// When this is done, jquery.treeview.js (for instance)
// can be unpatched.
- jQuery(CubicWeb).trigger('ajax-loaded');
+ jQuery(CubicWeb).trigger('ajax-loaded');
}
/* cubicweb loadxhtml plugin to make jquery handle xhtml response
@@ -87,38 +113,38 @@
jQuery.fn.loadxhtml = function(url, data, reqtype, mode) {
var ajax = null;
if (reqtype == 'post') {
- ajax = jQuery.post;
+ ajax = jQuery.post;
} else {
- ajax = jQuery.get;
+ ajax = jQuery.get;
}
if (this.size() > 1) {
- log('loadxhtml was called with more than one element');
+ log('loadxhtml was called with more than one element');
}
var node = this.get(0); // only consider the first element
mode = mode || 'replace';
var callback = null;
if (data && data.callback) {
- callback = data.callback;
- delete data.callback;
+ callback = data.callback;
+ delete data.callback;
}
ajax(url, data, function(response) {
- var domnode = getDomFromResponse(response);
- preprocessAjaxLoad(node, domnode);
- if (mode == 'swap') {
- var origId = node.id;
- node = swapDOM(node, domnode);
- if (!node.id) {
- node.id = origId;
- }
- } else if (mode == 'replace') {
- jQuery(node).empty().append(domnode);
- } else if (mode == 'append') {
- jQuery(node).append(domnode);
- }
- postAjaxLoad(node);
- while (jQuery.isFunction(callback)) {
- callback = callback.apply(this, [domnode]);
- }
+ var domnode = getDomFromResponse(response);
+ domnode = preprocessAjaxLoad(node, domnode);
+ if (mode == 'swap') {
+ var origId = node.id;
+ node = swapDOM(node, domnode);
+ if (!node.id) {
+ node.id = origId;
+ }
+ } else if (mode == 'replace') {
+ jQuery(node).empty().append(domnode);
+ } else if (mode == 'append') {
+ jQuery(node).append(domnode);
+ }
+ postAjaxLoad(node);
+ while (jQuery.isFunction(callback)) {
+ callback = callback.apply(this, [domnode]);
+ }
});
};
@@ -129,43 +155,43 @@
*/
function loadDynamicFragments(node) {
if (node) {
- var fragments = jQuery(node).find('div.dynamicFragment');
+ var fragments = jQuery(node).find('div.dynamicFragment');
} else {
- var fragments = jQuery('div.dynamicFragment');
+ var fragments = jQuery('div.dynamicFragment');
}
if (fragments.length == 0) {
- return;
+ return;
}
if (typeof LOADING_MSG == 'undefined') {
- LOADING_MSG = 'loading'; // this is only a safety belt, it should not happen
+ LOADING_MSG = 'loading'; // this is only a safety belt, it should not happen
}
for(var i=0; i<fragments.length; i++) {
- var fragment = fragments[i];
- fragment.innerHTML = '<h3>' + LOADING_MSG + ' ... <img src="data/loading.gif" /></h3>';
- // if cubicweb:loadurl is set, just pick the url et send it to loadxhtml
- var url = getNodeAttribute(fragment, 'cubicweb:loadurl');
- if (url) {
- jQuery(fragment).loadxhtml(url);
- continue;
- }
- // else: rebuild full url by fetching cubicweb:rql, cubicweb:vid, etc.
- var rql = getNodeAttribute(fragment, 'cubicweb:rql');
- var items = getNodeAttribute(fragment, 'cubicweb:vid').split('&');
- var vid = items[0];
+ var fragment = fragments[i];
+ fragment.innerHTML = '<h3>' + LOADING_MSG + ' ... <img src="data/loading.gif" /></h3>';
+ // if cubicweb:loadurl is set, just pick the url et send it to loadxhtml
+ var url = getNodeAttribute(fragment, 'cubicweb:loadurl');
+ if (url) {
+ jQuery(fragment).loadxhtml(url);
+ continue;
+ }
+ // else: rebuild full url by fetching cubicweb:rql, cubicweb:vid, etc.
+ var rql = getNodeAttribute(fragment, 'cubicweb:rql');
+ var items = getNodeAttribute(fragment, 'cubicweb:vid').split('&');
+ var vid = items[0];
var extraparams = {};
- // case where vid='myvid¶m1=val1¶m2=val2': this is a deprecated abuse-case
- if (items.length > 1) {
- console.log("[3.5] you're using extraargs in cubicweb:vid attribute, this is deprecated, consider using loadurl instead");
- for (var j=1; j<items.length; j++) {
- var keyvalue = items[j].split('=');
- extraparams[keyvalue[0]] = keyvalue[1];
- }
- }
- var actrql = getNodeAttribute(fragment, 'cubicweb:actualrql');
- if (actrql) { extraparams['actualrql'] = actrql; }
- var fbvid = getNodeAttribute(fragment, 'cubicweb:fallbackvid');
- if (fbvid) { extraparams['fallbackvid'] = fbvid; }
- replacePageChunk(fragment.id, rql, vid, extraparams);
+ // case where vid='myvid¶m1=val1¶m2=val2': this is a deprecated abuse-case
+ if (items.length > 1) {
+ console.log("[3.5] you're using extraargs in cubicweb:vid attribute, this is deprecated, consider using loadurl instead");
+ for (var j=1; j<items.length; j++) {
+ var keyvalue = items[j].split('=');
+ extraparams[keyvalue[0]] = keyvalue[1];
+ }
+ }
+ var actrql = getNodeAttribute(fragment, 'cubicweb:actualrql');
+ if (actrql) { extraparams['actualrql'] = actrql; }
+ var fbvid = getNodeAttribute(fragment, 'cubicweb:fallbackvid');
+ if (fbvid) { extraparams['fallbackvid'] = fbvid; }
+ replacePageChunk(fragment.id, rql, vid, extraparams);
}
}
@@ -175,9 +201,9 @@
function remoteCallFailed(err, req) {
if (req.status == 500) {
- updateMessage(err);
+ updateMessage(err);
} else {
- updateMessage(_("an error occured while processing your request"));
+ updateMessage(_("an error occured while processing your request"));
}
}
@@ -193,10 +219,10 @@
function remoteExec(fname /* ... */) {
setProgressCursor();
var props = {'fname' : fname, 'pageid' : pageid,
- 'arg': map(jQuery.toJSON, sliceList(arguments, 1))};
+ 'arg': map(jQuery.toJSON, sliceList(arguments, 1))};
var result = jQuery.ajax({url: JSON_BASE_URL, data: props, async: false}).responseText;
if (result) {
- result = evalJSON(result);
+ result = evalJSON(result);
}
resetCursor();
return result;
@@ -216,7 +242,7 @@
function asyncRemoteExec(fname /* ... */) {
setProgressCursor();
var props = {'fname' : fname, 'pageid' : pageid,
- 'arg': map(jQuery.toJSON, sliceList(arguments, 1))};
+ 'arg': map(jQuery.toJSON, sliceList(arguments, 1))};
var deferred = loadRemote(JSON_BASE_URL, props, 'POST');
deferred = deferred.addErrback(remoteCallFailed);
deferred = deferred.addErrback(resetCursor);
@@ -243,9 +269,9 @@
function openHash() {
if (document.location.hash) {
- var nid = document.location.hash.replace('#', '');
- var node = jQuery('#' + nid);
- if (node) { removeElementClass(node, "hidden"); }
+ var nid = document.location.hash.replace('#', '');
+ var node = jQuery('#' + nid);
+ if (node) { removeElementClass(node, "hidden"); }
};
}
jQuery(document).ready(openHash);
@@ -258,18 +284,18 @@
var node = getNode(nodeid);
var d = asyncRemoteExec('component', compid, rql, registry, extraargs);
d.addCallback(function(result, req) {
- var domnode = getDomFromResponse(result);
- if (node) {
- // make sure the component is visible
- removeElementClass(node, "hidden");
- swapDOM(node, domnode);
- postAjaxLoad(domnode);
- }
+ var domnode = getDomFromResponse(result);
+ if (node) {
+ // make sure the component is visible
+ removeElementClass(node, "hidden");
+ swapDOM(node, domnode);
+ postAjaxLoad(domnode);
+ }
});
d.addCallback(resetCursor);
d.addErrback(function(xxx) {
- updateMessage(_("an error occured"));
- log(xxx);
+ updateMessage(_("an error occured"));
+ log(xxx);
});
return d;
}
@@ -282,28 +308,28 @@
function userCallbackThenUpdateUI(cbname, compid, rql, msg, registry, nodeid) {
var d = asyncRemoteExec('user_callback', cbname);
d.addCallback(function() {
- reloadComponent(compid, rql, registry, nodeid);
- if (msg) { updateMessage(msg); }
+ reloadComponent(compid, rql, registry, nodeid);
+ if (msg) { updateMessage(msg); }
});
d.addCallback(resetCursor);
d.addErrback(function(xxx) {
- updateMessage(_("an error occured"));
- log(xxx);
- return resetCursor();
+ updateMessage(_("an error occured"));
+ log(xxx);
+ return resetCursor();
});
}
function userCallbackThenReloadPage(cbname, msg) {
var d = asyncRemoteExec('user_callback', cbname);
d.addCallback(function() {
- window.location.reload();
- if (msg) { updateMessage(msg); }
+ window.location.reload();
+ if (msg) { updateMessage(msg); }
});
d.addCallback(resetCursor);
d.addErrback(function(xxx) {
- updateMessage(_("an error occured"));
- log(xxx);
- return resetCursor();
+ updateMessage(_("an error occured"));
+ log(xxx);
+ return resetCursor();
});
}
@@ -315,9 +341,9 @@
var d = asyncRemoteExec('unregister_user_callback', cbname);
d.addCallback(function() {resetCursor();});
d.addErrback(function(xxx) {
- updateMessage(_("an error occured"));
- log(xxx);
- return resetCursor();
+ updateMessage(_("an error occured"));
+ log(xxx);
+ return resetCursor();
});
}
@@ -333,25 +359,25 @@
function replacePageChunk(nodeId, rql, vid, extraparams, /* ... */ swap, callback) {
var params = null;
if (callback) {
- params = {callback: callback};
+ params = {callback: callback};
}
var node = jQuery('#' + nodeId)[0];
var props = {};
if (node) {
- props['rql'] = rql;
- props['fname'] = 'view';
- props['pageid'] = pageid;
- if (vid) { props['vid'] = vid; }
- if (extraparams) { jQuery.extend(props, extraparams); }
- // FIXME we need to do asURL(props) manually instead of
- // passing `props` directly to loadxml because replacePageChunk
- // is sometimes called (abusively) with some extra parameters in `vid`
- var mode = swap?'swap':'replace';
- var url = JSON_BASE_URL + asURL(props);
- jQuery(node).loadxhtml(url, params, 'get', mode);
+ props['rql'] = rql;
+ props['fname'] = 'view';
+ props['pageid'] = pageid;
+ if (vid) { props['vid'] = vid; }
+ if (extraparams) { jQuery.extend(props, extraparams); }
+ // FIXME we need to do asURL(props) manually instead of
+ // passing `props` directly to loadxml because replacePageChunk
+ // is sometimes called (abusively) with some extra parameters in `vid`
+ var mode = swap?'swap':'replace';
+ var url = JSON_BASE_URL + asURL(props);
+ jQuery(node).loadxhtml(url, params, 'get', mode);
} else {
- log('Node', nodeId, 'not found');
+ log('Node', nodeId, 'not found');
}
}
@@ -374,20 +400,20 @@
*/
function buildWysiwygEditors(parent) {
jQuery('textarea').each(function () {
- if (this.getAttribute('cubicweb:type') == 'wysiwyg') {
+ if (this.getAttribute('cubicweb:type') == 'wysiwyg') {
// mark editor as instanciated, we may be called a number of times
// (see postAjaxLoad)
this.setAttribute('cubicweb:type', 'fckeditor');
- if (typeof FCKeditor != "undefined") {
- var fck = new FCKeditor(this.id);
- fck.Config['CustomConfigurationsPath'] = fckconfigpath;
- fck.Config['DefaultLanguage'] = fcklang;
- fck.BasePath = "fckeditor/";
- fck.ReplaceTextarea();
- } else {
- log('fckeditor could not be found.');
- }
- }
+ if (typeof FCKeditor != "undefined") {
+ var fck = new FCKeditor(this.id);
+ fck.Config['CustomConfigurationsPath'] = fckconfigpath;
+ fck.Config['DefaultLanguage'] = fcklang;
+ fck.BasePath = "fckeditor/";
+ fck.ReplaceTextarea();
+ } else {
+ log('fckeditor could not be found.');
+ }
+ }
});
}
@@ -400,12 +426,12 @@
function stripEmptyTextNodes(nodelist) {
var stripped = [];
for (var i=0; i < nodelist.length; i++) {
- var node = nodelist[i];
- if (isTextNode(node) && !node.textContent.strip()) {
- continue;
- } else {
- stripped.push(node);
- }
+ var node = nodelist[i];
+ if (isTextNode(node) && !node.textContent.strip()) {
+ continue;
+ } else {
+ stripped.push(node);
+ }
}
return stripped;
}
@@ -415,25 +441,25 @@
* */
function getDomFromResponse(response) {
if (typeof(response) == 'string') {
- var doc = html2dom(response);
+ var doc = html2dom(response);
} else {
var doc = response.documentElement;
}
var children = doc.childNodes;
if (!children.length) {
- // no child (error cases) => return the whole document
- return jQuery(doc).clone().context;
+ // no child (error cases) => return the whole document
+ return jQuery(doc).clone().context;
}
children = stripEmptyTextNodes(children);
if (children.length == 1) {
- // only one child => return it
- return jQuery(children[0]).clone().context;
+ // only one child => return it
+ return jQuery(children[0]).clone().context;
}
// several children => wrap them in a single node and return the wrap
- return DIV(null, map(function(node) {
- return jQuery(node).clone().context;
- },
- children));
+ return DIV({'cubicweb:type': "cwResponseWrapper"},
+ map(function(node) {
+ return jQuery(node).clone().context;
+ }, children));
}
function postJSON(url, data, callback) {