web/data/cubicweb.ajax.js
changeset 7427 06444c1233e0
parent 7377 d8083b2ae4d6
child 7433 9aadb5a04b53
equal deleted inserted replaced
7423:598a4f051259 7427:06444c1233e0
    20 /**
    20 /**
    21  * .. function:: Deferred
    21  * .. function:: Deferred
    22  *
    22  *
    23  * dummy ultra minimalist implementation of deferred for jQuery
    23  * dummy ultra minimalist implementation of deferred for jQuery
    24  */
    24  */
       
    25 
       
    26 cw.ajax = new Namespace('cw.ajax');
       
    27 
    25 function Deferred() {
    28 function Deferred() {
    26     this.__init__(this);
    29     this.__init__(this);
    27 }
    30 }
    28 
    31 
    29 jQuery.extend(Deferred.prototype, {
    32 jQuery.extend(Deferred.prototype, {
    84 });
    87 });
    85 
    88 
    86 
    89 
    87 var JSON_BASE_URL = baseuri() + 'json?';
    90 var JSON_BASE_URL = baseuri() + 'json?';
    88 
    91 
    89 /**
    92 
    90  * returns true if `url` is a mod_concat-like url
    93 jQuery.extend(cw.ajax, {
    91  * (e.g. http://..../data??resource1.js,resource2.js)
    94     /* variant of jquery evalScript with cache: true in ajax call */
    92  */
    95     _evalscript: function ( i, elem ) {
    93 function _modconcatLikeUrl(url) {
    96        if ( elem.src ) {
    94     var base = baseuri();
    97            jQuery.ajax({
    95     if (!base.endswith('/')) {
    98                url: elem.src,
    96         base += '/';
    99                async: false,
    97     }
   100                cache: true,
    98     var modconcat_rgx = new RegExp('(' + base + 'data/([a-z0-9]+/)?)\\?\\?(.+)');
   101                dataType: "script"
    99     return modconcat_rgx.exec(url);
   102            });
   100 }
   103        } else {
   101 
   104            jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
   102 /**
   105        }
   103  * decomposes a mod_concat-like url into its corresponding list of
   106        if ( elem.parentNode ) {
   104  * resources' urls
   107            elem.parentNode.removeChild( elem );
   105  *
   108        }
   106  * >>> _listResources('http://foo.com/data/??a.js,b.js,c.js')
   109     },
   107  * ['http://foo.com/data/a.js', 'http://foo.com/data/b.js', 'http://foo.com/data/c.js']
   110 
   108  */
   111     evalscripts: function ( scripts ) {
   109 function _listResources(src) {
   112         if ( scripts.length ) {
   110     var resources = [];
   113             jQuery.each(scripts, cw.ajax._evalscript);
   111     var groups = _modconcatLikeUrl(src);
   114         }
   112     if (groups == null) {
   115     },
   113         resources.push(src);
   116 
   114     } else {
   117     /**
   115         var dataurl = groups[1];
   118      * returns true if `url` is a mod_concat-like url
   116         $.each(cw.utils.lastOf(groups).split(','),
   119      * (e.g. http://..../data??resource1.js,resource2.js)
   117                function() {
   120      */
   118                    resources.push(dataurl + this);
   121     _modconcatLikeUrl: function(url) {
   119                });
   122         var base = baseuri();
   120     }
   123         if (!base.endswith('/')) { base += '/'; }
   121     return resources;
   124         var modconcat_rgx = new RegExp('(' + base + 'data/([a-z0-9]+/)?)\\?\\?(.+)');
   122 }
   125         return modconcat_rgx.exec(url);
       
   126     },
       
   127 
       
   128     /**
       
   129      * decomposes a mod_concat-like url into its corresponding list of
       
   130      * resources' urls
       
   131      * >>> _listResources('http://foo.com/data/??a.js,b.js,c.js')
       
   132      * ['http://foo.com/data/a.js', 'http://foo.com/data/b.js', 'http://foo.com/data/c.js']
       
   133      */
       
   134     _listResources: function(src) {
       
   135         var resources = [];
       
   136         var groups = cw.ajax._modconcatLikeUrl(src);
       
   137         if (groups == null) {
       
   138             resources.push(src);
       
   139         } else {
       
   140             var dataurl = groups[1];
       
   141             $.each(cw.utils.lastOf(groups).split(','),
       
   142                  function() {
       
   143                      resources.push(dataurl + this);
       
   144                  }
       
   145             );
       
   146         }
       
   147         return resources;
       
   148     }
       
   149 });
   123 
   150 
   124 //============= utility function handling remote calls responses. ==============//
   151 //============= utility function handling remote calls responses. ==============//
   125 function _loadAjaxHtmlHead($node, $head, tag, srcattr) {
   152 function _loadAjaxHtmlHead($node, $head, tag, srcattr) {
   126     var jqtagfilter = tag + '[' + srcattr + ']';
   153     var jqtagfilter = tag + '[' + srcattr + ']';
   127     if (cw['loaded_'+srcattr] === undefined) {
   154     if (cw['loaded_'+srcattr] === undefined) {
   128         cw['loaded_'+srcattr] = [];
   155         cw['loaded_'+srcattr] = [];
   129         var loaded = cw['loaded_'+srcattr];
   156         var loaded = cw['loaded_'+srcattr];
   130         jQuery('head ' + jqtagfilter).each(function(i) {
   157         jQuery('head ' + jqtagfilter).each(function(i) {
   131             // tab1.push.apply(tab1, tab2) <=> tab1 += tab2 (python-wise)
   158             // tab1.push.apply(tab1, tab2) <=> tab1 += tab2 (python-wise)
   132             loaded.push.apply(loaded, _listResources(this.getAttribute(srcattr)));
   159             loaded.push.apply(loaded, cw.ajax._listResources(this.getAttribute(srcattr)));
   133         });
   160         });
   134     } else {
   161     } else {
   135         var loaded = cw['loaded_'+srcattr];
   162         var loaded = cw['loaded_'+srcattr];
   136     }
   163     }
   137     $node.find(tag).each(function(i) {
   164     $node.find(tag).each(function(i) {
   138         var srcnode = this;
   165         var $srcnode = jQuery(this);
   139         var url = srcnode.getAttribute(srcattr);
   166         var url = $srcnode.attr(srcattr);
   140         if (url) {
   167         if (url) {
   141             $.each(_listResources(url), function() {
   168             /* special handling of <script> tags: script nodes appended by jquery
   142                 var resource = '' + this; // implicit object->string cast
   169              * use uncached ajax calls and do not appear in the DOM
   143                 if ($.inArray(resource, loaded) == -1) {
   170              * (See comments in response to Syt on // http://api.jquery.com/append/),
   144                     // take care to <script> tags: jQuery append method script nodes
   171              * which cause undesired duplicated load in our case. We now handle
   145                     // don't appears in the DOM (See comments on
   172              * a list of already loaded resources, since bare DOM api gives bugs with the
   146                     // http://api.jquery.com/append/), which cause undesired
   173              * server-response event, and we lose control on when the
   147                     // duplicated load in our case. After trying to use bare DOM api
   174              * script is loaded (jQuery loads it immediately). */
   148                     // to avoid this, we switched to handle a list of already loaded
   175             var resources = cw.ajax._listResources(url);
   149                     // stuff ourselves, since bare DOM api gives bug with the
   176             var missingResources = $.grep(resources, function(resource) {
   150                     // server-response event, since we loose control on when the
   177                 return $.inArray(resource, loaded) == -1;
   151                     // script is loaded (jQuery load it immediatly).
       
   152                     loaded.push(resource);
       
   153                 }
       
   154             });
   178             });
   155         }
   179             loaded.push.apply(loaded, missingResources);
   156 	jQuery(srcnode).appendTo($head);
   180             if (missingResources.length == 1) {
       
   181                 // only one resource missing: build a node with a single resource url
       
   182                 // (maybe the browser has it in cache already)
       
   183                 $srcnode.attr(srcattr, missingResources[0]);
       
   184             } else if (missingResources.length > 1) {
       
   185                 // several resources missing: build a node with a concatenated
       
   186                 // resources url
       
   187                 var dataurl = cw.ajax._modconcatLikeUrl(url)[1];
       
   188                 var missing_path = $.map(missingResources, function(resource) {
       
   189                     return resource.substring(dataurl.length);
       
   190                 });
       
   191                 $srcnode.attr(srcattr, dataurl + '??' + missing_path.join(','));
       
   192             }
       
   193             // === will work if both arguments are of the same type
       
   194             if ( $srcnode.attr('type') === 'text/javascript' ) {
       
   195                 cw.ajax.evalscripts($srcnode);
       
   196             } else {
       
   197                 $srcnode.appendTo($head);
       
   198             }
       
   199         }
   157     });
   200     });
   158     $node.find(jqtagfilter).remove();
   201     $node.find(jqtagfilter).remove();
   159 }
   202 }
   160 
   203 
   161 /**
   204 /**