--- a/utils.py Mon Jul 11 19:48:37 2011 +0200
+++ b/utils.py Tue Jul 12 10:36:22 2011 +0200
@@ -362,13 +362,33 @@
# 4/ js files
jsfiles = ((x, None) for x in self.jsfiles)
for jsfile, media in self.group_urls(jsfiles) if self.datadir_url else jsfiles:
- w(u'<script type="text/javascript" src="%s"></script>\n' %
- xml_escape(jsfile))
+ if skiphead:
+ # Don't insert <script> tags directly as they would be
+ # interpreted directly by some browsers (e.g. IE).
+ # Use <pre class="script"> tags instead and let
+ # `loadAjaxHtmlHead` handle the script insertion / execution.
+ w(u'<pre class="script" src="%s"></pre>\n' %
+ xml_escape(jsfile))
+ # FIXME: a probably better implementation might be to add
+ # JS or CSS urls in a JS list that loadAjaxHtmlHead
+ # would iterate on and postprocess:
+ # cw._ajax_js_scripts.push('myscript.js')
+ # Then, in loadAjaxHtmlHead, do something like:
+ # jQuery.each(cw._ajax_js_script, jQuery.getScript)
+ else:
+ w(u'<script type="text/javascript" src="%s"></script>\n' %
+ xml_escape(jsfile))
# 5/ post inlined scripts (i.e. scripts depending on other JS files)
if self.post_inlined_scripts:
- w(self.xhtml_safe_script_opening)
- w(u'\n\n'.join(self.post_inlined_scripts))
- w(self.xhtml_safe_script_closing)
+ if skiphead:
+ for script in self.post_inlined_scripts:
+ w(u'<pre class="script">')
+ w(script)
+ w(u'</pre>')
+ else:
+ w(self.xhtml_safe_script_opening)
+ w(u'\n\n'.join(self.post_inlined_scripts))
+ w(self.xhtml_safe_script_closing)
header = super(HTMLHead, self).getvalue()
if skiphead:
return header
--- a/web/data/cubicweb.ajax.js Mon Jul 11 19:48:37 2011 +0200
+++ b/web/data/cubicweb.ajax.js Tue Jul 12 10:36:22 2011 +0200
@@ -93,9 +93,10 @@
jQuery.extend(cw.ajax, {
/* variant of jquery evalScript with cache: true in ajax call */
_evalscript: function ( i, elem ) {
- if ( elem.src ) {
+ var src = elem.getAttribute('src');
+ if (src) {
jQuery.ajax({
- url: elem.src,
+ url: src,
async: false,
cache: true,
dataType: "script"
@@ -145,62 +146,76 @@
);
}
return resources;
+ },
+
+ _buildMissingResourcesUrl: function(url, loadedResources) {
+ var resources = cw.ajax._listResources(url);
+ var missingResources = $.grep(resources, function(resource) {
+ return $.inArray(resource, loadedResources) == -1;
+ });
+ cw.utils.extend(loadedResources, missingResources);
+ var missingResourceUrl = null;
+ if (missingResources.length == 1) {
+ // only one resource missing: build a node with a single resource url
+ // (maybe the browser has it in cache already)
+ missingResourceUrl = missingResources[0];
+ } else if (missingResources.length > 1) {
+ // several resources missing: build a node with a concatenated
+ // resources url
+ var dataurl = cw.ajax._modconcatLikeUrl(url)[1];
+ var missing_path = $.map(missingResources, function(resource) {
+ return resource.substring(dataurl.length);
+ });
+ missingResourceUrl = dataurl + '??' + missing_path.join(',');
+ }
+ return missingResourceUrl;
+ },
+
+ _loadAjaxStylesheets: function($responseHead, $head) {
+ $responseHead.find('link[href]').each(function(i) {
+ var $srcnode = $(this);
+ var url = $srcnode.attr('href');
+ if (url) {
+ var missingStylesheetsUrl = cw.ajax._buildMissingResourcesUrl(url, cw.loaded_links);
+ // compute concat-like url for missing resources and append <link>
+ // element to $head
+ if (missingStylesheetsUrl) {
+ $srcnode.attr('href', missingStylesheetsUrl);
+ $srcnode.appendTo($head);
+ }
+ }
+ });
+ $responseHead.find('link[href]').remove();
+ },
+
+ _loadAjaxScripts: function($responseHead, $head) {
+ $responseHead.find('pre.script').each(function(i) {
+ var $srcnode = $(this);
+ var url = $srcnode.attr('src');
+ if (url) {
+ var missingScriptsUrl = cw.ajax._buildMissingResourcesUrl(url, cw.loaded_scripts);
+ if (missingScriptsUrl) {
+ $srcnode.attr('src', missingScriptsUrl);
+ /* special handling of <script> tags: script nodes appended by jquery
+ * use uncached ajax calls and do not appear in the DOM
+ * (See comments in response to Syt on // http://api.jquery.com/append/),
+ * which cause undesired duplicated load in our case. We now handle
+ * a list of already loaded resources, since bare DOM api gives bugs with the
+ * server-response event, and we lose control on when the
+ * script is loaded (jQuery loads it immediately). */
+ cw.ajax.evalscripts($srcnode);
+ }
+ } else {
+ // <script> contains inlined javascript code, node content
+ // must be evaluated
+ jQuery.globalEval($srcnode.text());
+ }
+ });
+ $responseHead.find('pre.script').remove();
}
});
//============= utility function handling remote calls responses. ==============//
-function _loadAjaxHtmlHead($node, $head, tag, srcattr) {
- var jqtagfilter = tag + '[' + srcattr + ']';
- if (cw['loaded_'+srcattr] === undefined) {
- cw['loaded_'+srcattr] = [];
- var loaded = cw['loaded_'+srcattr];
- jQuery('head ' + jqtagfilter).each(function(i) {
- // tab1.push.apply(tab1, tab2) <=> tab1 += tab2 (python-wise)
- loaded.push.apply(loaded, cw.ajax._listResources(this.getAttribute(srcattr)));
- });
- } else {
- var loaded = cw['loaded_'+srcattr];
- }
- $node.find(tag).each(function(i) {
- var $srcnode = jQuery(this);
- var url = $srcnode.attr(srcattr);
- if (url) {
- /* special handling of <script> tags: script nodes appended by jquery
- * use uncached ajax calls and do not appear in the DOM
- * (See comments in response to Syt on // http://api.jquery.com/append/),
- * which cause undesired duplicated load in our case. We now handle
- * a list of already loaded resources, since bare DOM api gives bugs with the
- * server-response event, and we lose control on when the
- * script is loaded (jQuery loads it immediately). */
- var resources = cw.ajax._listResources(url);
- var missingResources = $.grep(resources, function(resource) {
- return $.inArray(resource, loaded) == -1;
- });
- loaded.push.apply(loaded, missingResources);
- if (missingResources.length == 1) {
- // only one resource missing: build a node with a single resource url
- // (maybe the browser has it in cache already)
- $srcnode.attr(srcattr, missingResources[0]);
- } else if (missingResources.length > 1) {
- // several resources missing: build a node with a concatenated
- // resources url
- var dataurl = cw.ajax._modconcatLikeUrl(url)[1];
- var missing_path = $.map(missingResources, function(resource) {
- return resource.substring(dataurl.length);
- });
- $srcnode.attr(srcattr, dataurl + '??' + missing_path.join(','));
- } else { return ; }
- // === will work if both arguments are of the same type
- if ( $srcnode.attr('type') === 'text/javascript' ) {
- cw.ajax.evalscripts($srcnode);
- } else {
- $srcnode.appendTo($head);
- }
- }
- });
- $node.find(jqtagfilter).remove();
-}
-
/**
* .. function:: function loadAjaxHtmlHead(response)
*
@@ -216,8 +231,8 @@
if (!$responseHead.length) {
return response;
}
- _loadAjaxHtmlHead($responseHead, $head, 'script', 'src');
- _loadAjaxHtmlHead($responseHead, $head, 'link', 'href');
+ cw.ajax._loadAjaxStylesheets($responseHead, $head);
+ cw.ajax._loadAjaxScripts($responseHead, $head);
// add any remaining children (e.g. meta)
$responseHead.children().appendTo($head);
// remove original container, which is now empty
@@ -487,11 +502,6 @@
$fragment.loadxhtml('json', ajaxFuncArgs('view', extraparams));
}
}
-
-jQuery(document).ready(function() {
- _loadDynamicFragments();
-});
-
function unloadPageData() {
// NOTE: do not make async calls on unload if you want to avoid
// strange bugs
@@ -817,3 +827,16 @@
deferred = deferred.addCallback(resetCursor);
return deferred;
}
+
+jQuery(document).ready(function() {
+ _loadDynamicFragments();
+ // build loaded_scripts / loaded_links lists
+ cw.loaded_scripts = [];
+ jQuery('head script[src]').each(function(i) {
+ cw.utils.extend(cw.loaded_scripts, cw.ajax._listResources(this.getAttribute('src')));
+ });
+ cw.loaded_links = [];
+ jQuery('head link[href]').each(function(i) {
+ cw.utils.extend(cw.loaded_links, cw.ajax._listResources(this.getAttribute('href')));
+ });
+});
--- a/web/data/cubicweb.js Mon Jul 11 19:48:37 2011 +0200
+++ b/web/data/cubicweb.js Tue Jul 12 10:36:22 2011 +0200
@@ -318,6 +318,17 @@
}
},
+
+ /**
+ * .. function:: extend(array1, array2)
+ *
+ * equivalent of python ``+=`` statement on lists (array1 += array2)
+ */
+ extend: function(array1, array2) {
+ array1.push.apply(array1, array2);
+ return array1; // return array1 for convenience
+ },
+
/**
* .. function:: difference(lst1, lst2)
*