mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
Merge branch 'MDL-57009-master' of git://github.com/damyon/moodle
This commit is contained in:
commit
cf8c463de6
2
lib/amd/build/ajax.min.js
vendored
2
lib/amd/build/ajax.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/config"],function(a,b){var c=function(a){var b,c,d=this,e=null,f=0;for(f=0;f<d.length;f++){if(b=d[f],c=a[f],"undefined"==typeof c){e=new Error("missing response");break}if(c.error!==!1){e=c.exception;break}b.deferred.resolve(c.data)}if(null!==e)for(;f<d.length;f++)b=d[f],b.deferred.reject(e)},d=function(a,b){var c=this,d=0;for(d=0;d<c.length;d++){var e=c[d];"undefined"!=typeof e.fail&&e.deferred.reject(b)}};return{call:function(e,f,g){var h,i=[],j=[];for("undefined"==typeof g&&(g=!0),"undefined"==typeof f&&(f=!0),h=0;h<e.length;h++){var k=e[h];i.push({index:h,methodname:k.methodname,args:k.args}),k.deferred=a.Deferred(),j.push(k.deferred.promise()),"undefined"!=typeof k.done&&k.deferred.done(k.done),"undefined"!=typeof k.fail&&k.deferred.fail(k.fail),k.index=h}i=JSON.stringify(i);var l={type:"POST",data:i,context:e,dataType:"json",processData:!1,async:f,contentType:"application/json"},m=b.wwwroot+"/lib/ajax/service.php?sesskey="+b.sesskey;return g||(m=b.wwwroot+"/lib/ajax/service-nologin.php?sesskey="+b.sesskey),f?a.ajax(m,l).done(c).fail(d):(l.success=c,l.error=d,a.ajax(m,l)),j}}});
|
||||
define(["jquery","core/config"],function(a,b){var c=function(a){var b,c,d=this,e=null,f=0;for(f=0;f<d.length;f++){if(b=d[f],c=a[f],"undefined"==typeof c){e=new Error("missing response");break}if(c.error!==!1){e=c.exception;break}b.deferred.resolve(c.data)}if(null!==e)for(;f<d.length;f++)b=d[f],b.deferred.reject(e)},d=function(a,b){var c=this,d=0;for(d=0;d<c.length;d++){var e=c[d];e.deferred.reject(b)}};return{call:function(e,f,g){var h,i=[],j=[];for("undefined"==typeof g&&(g=!0),"undefined"==typeof f&&(f=!0),h=0;h<e.length;h++){var k=e[h];i.push({index:h,methodname:k.methodname,args:k.args}),k.deferred=a.Deferred(),j.push(k.deferred.promise()),"undefined"!=typeof k.done&&k.deferred.done(k.done),"undefined"!=typeof k.fail&&k.deferred.fail(k.fail),k.index=h}i=JSON.stringify(i);var l={type:"POST",data:i,context:e,dataType:"json",processData:!1,async:f,contentType:"application/json"},m=b.wwwroot+"/lib/ajax/service.php?sesskey="+b.sesskey;return g||(m=b.wwwroot+"/lib/ajax/service-nologin.php?sesskey="+b.sesskey),f?a.ajax(m,l).done(c).fail(d):(l.success=c,l.error=d,a.ajax(m,l)),j}}});
|
2
lib/amd/build/str.min.js
vendored
2
lib/amd/build/str.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/ajax","core/localstorage"],function(a,b,c){return{get_string:function(a,b,c,d){var e=this.get_strings([{key:a,component:b,param:c,lang:d}]);return e.then(function(a){return a[0]})},get_strings:function(d){var e,f=a.Deferred(),g=[],h=0,i=!1;for(h=0;h<d.length;h++)if(e=d[h],"undefined"==typeof e.lang&&(e.lang=a("html").attr("lang").replace("-","_")),"undefined"==typeof M.str[e.component]||"undefined"==typeof M.str[e.component][e.key]){var j=c.get("core_str/"+e.key+"/"+e.component+"/"+e.lang);j?("undefined"==typeof M.str[e.component]&&(M.str[e.component]=[]),M.str[e.component][e.key]=j):i=!0}if(i){var k=[];for(h=0;h<d.length;h++)e=d[h],k.push({methodname:"core_get_string",args:{stringid:e.key,component:e.component,lang:e.lang,stringparams:[]}});var l=b.call(k,!0,!1);a.when.apply(null,l).done(function(){var a=0;for(a=0;a<arguments.length;a++)e=d[a],"undefined"==typeof M.str[e.component]&&(M.str[e.component]=[]),M.str[e.component][e.key]=arguments[a],c.set("core_str/"+e.key+"/"+e.component+"/"+e.lang,arguments[a]),g[a]=M.util.get_string(e.key,e.component,e.param).trim();f.resolve(g)}).fail(function(a){f.reject(a)})}else{for(h=0;h<d.length;h++)e=d[h],g[h]=M.util.get_string(e.key,e.component,e.param);f.resolve(g)}return f.promise()}}});
|
||||
define(["jquery","core/ajax","core/localstorage"],function(a,b,c){var d=[];return{get_string:function(a,b,c,d){var e=this.get_strings([{key:a,component:b,param:c,lang:d}]);return e.then(function(a){return a[0]})},get_strings:function(e){var f,g=a.Deferred(),h=[],i=0,j=!1;for(i=0;i<e.length;i++)if(f=e[i],"undefined"==typeof f.lang&&(f.lang=a("html").attr("lang").replace("-","_")),f.cacheKey="core_str/"+f.key+"/"+f.component+"/"+f.lang,"undefined"==typeof M.str[f.component]||"undefined"==typeof M.str[f.component][f.key]){var k=c.get(f.cacheKey);k?("undefined"==typeof M.str[f.component]&&(M.str[f.component]=[]),M.str[f.component][f.key]=k):j=!0}if(j){var l=[],m=[],n=function(a){this.resolve(a)},o=function(a){this.reject(a)};for(i=0;i<e.length;i++)if(f=e[i],"undefined"!=typeof d[f.cacheKey])m.push(d[f.cacheKey]);else{var p=a.Deferred();l.push({methodname:"core_get_string",args:{stringid:f.key,component:f.component,lang:f.lang,stringparams:[]},done:n.bind(p),fail:o.bind(p)}),d[f.cacheKey]=p.promise(),m.push(d[f.cacheKey])}l.length>0&&b.call(l,!0,!1),a.when.apply(null,m).done(function(){var a=0;for(a=0;a<arguments.length;a++)f=e[a],"undefined"==typeof M.str[f.component]&&(M.str[f.component]=[]),M.str[f.component][f.key]=arguments[a],c.set("core_str/"+f.key+"/"+f.component+"/"+f.lang,arguments[a]),h[a]=M.util.get_string(f.key,f.component,f.param).trim();g.resolve(h)}).fail(function(a){g.reject(a)})}else{for(i=0;i<e.length;i++)f=e[i],h[i]=M.util.get_string(f.key,f.component,f.param);g.resolve(h)}return g.promise()}}});
|
2
lib/amd/build/templates.min.js
vendored
2
lib/amd/build/templates.min.js
vendored
@ -1 +1 @@
|
||||
define(["core/mustache","jquery","core/ajax","core/str","core/notification","core/url","core/config","core/localstorage","core/event","core/yui","core/log"],function(a,b,c,d,e,f,g,h,i,j,k){var l=0,m={},n=function(){this.requiredStrings=[],this.requiredJS=[],this.currentThemeName=""};n.prototype.requiredStrings=null,n.prototype.requiredJS=null,n.prototype.currentThemeName="",n.prototype.getTemplate=function(a,d){var e=b.Deferred(),f=a.split("/"),g=f.shift(),i=f.shift(),j=this.currentThemeName+"/"+a;if(j in m)return e.resolve(m[j]),e.promise();var k=h.get("core_template/"+j);if(k)return e.resolve(k),m[j]=k,e.promise();var l=c.call([{methodname:"core_output_load_template",args:{component:g,template:i,themename:this.currentThemeName}}],d,!1);return l[0].done(function(a){h.set("core_template/"+j,a),m[j]=a,e.resolve(a)}).fail(function(a){e.reject(a)}),e.promise()},n.prototype.partialHelper=function(a){var b="";return this.getTemplate(a,!1).done(function(a){b=a}).fail(e.exception),b},n.prototype.pixHelper=function(b,c,d){var e,g=c.split(","),h="",i="",j="";g.length>0&&(h=g.shift().trim()),g.length>0&&(i=g.shift().trim()),g.length>0&&(j=g.join(",").trim());var k=f.imageUrl(h,i),l={attributes:[{name:"src",value:k},{name:"alt",value:d(j)},{name:"title",value:d(j)},{name:"class",value:"smallicon"}]},n=m[this.currentThemeName+"/core/pix_icon"];return e=a.render(n,l,this.partialHelper.bind(this)),e.trim()},n.prototype.jsHelper=function(a,b,c){return this.requiredJS.push(c(b,a)),""},n.prototype.stringHelper=function(a,b,c){var d=b.split(","),e="",f="",g="";d.length>0&&(e=d.shift().trim()),d.length>0&&(f=d.shift().trim()),d.length>0&&(g=d.join(",").trim()),""!==g&&(g=c(g,a)),0===g.indexOf("{")&&0!==g.indexOf("{{")&&(g=JSON.parse(g));var h=this.requiredStrings.length;return this.requiredStrings.push({key:e,component:f,param:g}),"[[_s"+h+"]]"},n.prototype.quoteHelper=function(a,b,c){var d=c(b.trim(),a);return d=d.replace('"','\\"').replace(/([\{\}]{2,3})/g,"{{=<% %>=}}$1<%={{ }}=%>"),'"'+d+'"'},n.prototype.addHelpers=function(a,b){this.currentThemeName=b,this.requiredStrings=[],this.requiredJS=[],a.uniqid=l++,a.str=function(){return this.stringHelper.bind(this,a)}.bind(this),a.pix=function(){return this.pixHelper.bind(this,a)}.bind(this),a.js=function(){return this.jsHelper.bind(this,a)}.bind(this),a.quote=function(){return this.quoteHelper.bind(this,a)}.bind(this),a.globals={config:g},a.currentTheme=b},n.prototype.getJS=function(a){var b="";return this.requiredJS.length>0&&(b=this.requiredJS.join(";\n")),this.treatStringsInContent(b,a)},n.prototype.treatStringsInContent=function(a,b){var c,d,e,f,g,h,i=/\[\[_s\d+\]\]/;do{for(c="",d=a.search(i);d>-1;){c+=a.substring(0,d),a=a.substr(d),e="",f=4,g=a.substr(f,1);do e+=g,f++,g=a.substr(f,1);while("]"!=g);h=b[parseInt(e,10)],"undefined"==typeof h&&(k.debug("Could not find string for pattern [[_s"+e+"]]."),h=""),c+=h,a=a.substr(6+e.length),d=a.search(i)}a=c+a,d=a.search(i)}while(d>-1);return a},n.prototype.doRender=function(c,e,f){var g=b.Deferred();this.currentThemeName=f;var h=this.getTemplate("core/pix_icon",!0);return h.done(function(){this.addHelpers(e,f);var b="";try{b=a.render(c,e,this.partialHelper.bind(this))}catch(h){g.reject(h)}this.requiredStrings.length>0?d.get_strings(this.requiredStrings).then(function(a){b=this.treatStringsInContent(b,a),g.resolve(b,this.getJS(a))}.bind(this)).fail(g.reject):g.resolve(b.trim(),this.getJS([]))}.bind(this)).fail(g.reject),g.promise()};var o=function(a){if(""!==a.trim()){var c=b("<script>").attr("type","text/javascript").html(a);b("head").append(c)}},p=function(a,c,d,e){var f=b(a);if(f.length){var g=b(c),h=null;e?(h=new j.NodeList(f.children().get()),h.destroy(!0),f.empty(),f.append(g)):(h=new j.NodeList(f.get()),h.destroy(!0),f.replaceWith(g)),o(d),i.notifyFilterContentUpdated(g)}};n.prototype.render=function(a,c,d){var e=b.Deferred();"undefined"==typeof d&&(d=g.theme),this.currentThemeName=d;var f=this.getTemplate(a,!0);return f.done(function(a){var b=this.doRender(a,c,d);b.done(function(a,b){e.resolve(a,b)}).fail(function(a){e.reject(a)})}.bind(this)).fail(function(a){e.reject(a)}),e.promise()};var q=function(a,c,d){var e=b(a);e.length&&(e.prepend(c),o(d),i.notifyFilterContentUpdated(e))},r=function(a,c,d){var e=b(a);e.length&&(e.append(c),o(d),i.notifyFilterContentUpdated(e))};return{render:function(a,b,c){var d=new n;return d.render(a,b,c)},runTemplateJS:o,replaceNodeContents:function(a,b,c){p(a,b,c,!0)},replaceNode:function(a,b,c){p(a,b,c,!1)},prependNodeContents:function(a,b,c){q(a,b,c)},appendNodeContents:function(a,b,c){r(a,b,c)}}});
|
||||
define(["core/mustache","jquery","core/ajax","core/str","core/notification","core/url","core/log","core/config","core/localstorage","core/event","core/yui","core/log"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=0,n={},o={},p=function(){this.requiredStrings=[],this.requiredJS=[],this.currentThemeName=""};p.prototype.requiredStrings=null,p.prototype.requiredJS=null,p.prototype.currentThemeName="",p.prototype.getTemplate=function(a){var d=a.split("/"),e=d.shift(),f=d.shift(),g=this.currentThemeName+"/"+a;if(g in o)return o[g];var h=i.get("core_template/"+g);if(h)return n[g]=h,o[g]=b.Deferred().resolve(h).promise(),o[g];var j=c.call([{methodname:"core_output_load_template",args:{component:e,template:f,themename:this.currentThemeName}}],!0,!1);return o[g]=j[0].then(function(a){return n[g]=a,i.set("core_template/"+g,a),a}),o[g]},p.prototype.partialHelper=function(a){var b=this.currentThemeName+"/"+a;return b in n||e.exception(new Error("Failed to pre-fetch the template: "+a)),n[b]},p.prototype.pixHelper=function(b,c,d){var e,g=c.split(","),h="",i="",j="";g.length>0&&(h=g.shift().trim()),g.length>0&&(i=g.shift().trim()),g.length>0&&(j=g.join(",").trim());var k=f.imageUrl(h,i),l={attributes:[{name:"src",value:k},{name:"alt",value:d(j)},{name:"title",value:d(j)},{name:"class",value:"smallicon"}]},m=this.currentThemeName+"/core/pix_icon",o=n[m];return e=a.render(o,l,this.partialHelper.bind(this)),e.trim()},p.prototype.jsHelper=function(a,b,c){return this.requiredJS.push(c(b,a)),""},p.prototype.stringHelper=function(a,b,c){var d=b.split(","),e="",f="",g="";d.length>0&&(e=d.shift().trim()),d.length>0&&(f=d.shift().trim()),d.length>0&&(g=d.join(",").trim()),""!==g&&(g=c(g,a)),0===g.indexOf("{")&&0!==g.indexOf("{{")&&(g=JSON.parse(g));var h=this.requiredStrings.length;return this.requiredStrings.push({key:e,component:f,param:g}),"[[_s"+h+"]]"},p.prototype.quoteHelper=function(a,b,c){var d=c(b.trim(),a);return d=d.replace('"','\\"').replace(/([\{\}]{2,3})/g,"{{=<% %>=}}$1<%={{ }}=%>"),'"'+d+'"'},p.prototype.addHelpers=function(a,b){this.currentThemeName=b,this.requiredStrings=[],this.requiredJS=[],a.uniqid=m++,a.str=function(){return this.stringHelper.bind(this,a)}.bind(this),a.pix=function(){return this.pixHelper.bind(this,a)}.bind(this),a.js=function(){return this.jsHelper.bind(this,a)}.bind(this),a.quote=function(){return this.quoteHelper.bind(this,a)}.bind(this),a.globals={config:h},a.currentTheme=b},p.prototype.getJS=function(a){var b="";return this.requiredJS.length>0&&(b=this.requiredJS.join(";\n")),this.treatStringsInContent(b,a)},p.prototype.treatStringsInContent=function(a,b){var c,d,e,f,g,h,i=/\[\[_s\d+\]\]/;do{for(c="",d=a.search(i);d>-1;){c+=a.substring(0,d),a=a.substr(d),e="",f=4,g=a.substr(f,1);do e+=g,f++,g=a.substr(f,1);while("]"!=g);h=b[parseInt(e,10)],"undefined"==typeof h&&(l.debug("Could not find string for pattern [[_s"+e+"]]."),h=""),c+=h,a=a.substr(6+e.length),d=a.search(i)}a=c+a,d=a.search(i)}while(d>-1);return a},p.prototype.doRender=function(c,e,f){return this.currentThemeName=f,this.getTemplate("core/pix_icon").then(function(){this.addHelpers(e,f);var g=a.render(c,e,this.partialHelper.bind(this));return this.requiredStrings.length>0?d.get_strings(this.requiredStrings).then(function(a){return g=this.treatStringsInContent(g,a),b.Deferred().resolve(g,this.getJS(a)).promise()}.bind(this)):b.Deferred().resolve(g.trim(),this.getJS([])).promise()}.bind(this))};var q=function(a){if(""!==a.trim()){var c=b("<script>").attr("type","text/javascript").html(a);b("head").append(c)}},r=function(a,c,d,e){var f=b(a);if(f.length){var g=b(c),h=null;e?(h=new k.NodeList(f.children().get()),h.destroy(!0),f.empty(),f.append(g)):(h=new k.NodeList(f.get()),h.destroy(!0),f.replaceWith(g)),q(d),j.notifyFilterContentUpdated(g)}};p.prototype.scanForPartials=function(b){var c=a.parse(b),d=[],e=function(a,b){var c,d;for(c=0;c<a.length;c++)d=a[c],">"!=d[0]&&"<"!=d[0]||b.push(d[1]),d.length>4&&e(d[4],b)};return e(c,d),d},p.prototype.cachePartials=function(a){return this.getTemplate(a).then(function(a){var c,d=this.scanForPartials(a),e=[];for(c=0;c<d.length;c++){var f=this.currentThemeName+"/"+d[c];f in o||e.push(this.cachePartials(d[c]))}return b.when.apply(b,e).then(function(){return a})}.bind(this))},p.prototype.render=function(a,b,c){return"undefined"==typeof c&&(c=h.theme),this.currentThemeName=c,this.cachePartials(a).then(function(a){return this.doRender(a,b,c)}.bind(this))};var s=function(a,c,d){var e=b(a);e.length&&(e.prepend(c),q(d),j.notifyFilterContentUpdated(e))},t=function(a,c,d){var e=b(a);e.length&&(e.append(c),q(d),j.notifyFilterContentUpdated(e))};return{render:function(a,b,c){var d=new p;return d.render(a,b,c)},runTemplateJS:q,replaceNodeContents:function(a,b,c){r(a,b,c,!0)},replaceNode:function(a,b,c){r(a,b,c,!1)},prependNodeContents:function(a,b,c){s(a,b,c)},appendNodeContents:function(a,b,c){t(a,b,c)}}});
|
@ -87,9 +87,7 @@ define(['jquery', 'core/config'], function($, config) {
|
||||
for (i = 0; i < requests.length; i++) {
|
||||
var request = requests[i];
|
||||
|
||||
if (typeof request.fail != "undefined") {
|
||||
request.deferred.reject(textStatus);
|
||||
}
|
||||
request.deferred.reject(textStatus);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
/* eslint-disable no-restricted-properties */
|
||||
define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage) {
|
||||
|
||||
var promiseCache = [];
|
||||
|
||||
return /** @alias module:core/str */ {
|
||||
// Public variables and functions.
|
||||
@ -71,6 +72,7 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
|
||||
var i = 0;
|
||||
var missing = false;
|
||||
var request;
|
||||
|
||||
// Try from local storage. If it's there - put it in M.str and resolve it.
|
||||
|
||||
for (i = 0; i < requests.length; i++) {
|
||||
@ -78,10 +80,11 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
|
||||
if (typeof request.lang === "undefined") {
|
||||
request.lang = $('html').attr('lang').replace('-', '_');
|
||||
}
|
||||
request.cacheKey = 'core_str/' + request.key + '/' + request.component + '/' + request.lang;
|
||||
if (typeof M.str[request.component] === "undefined" ||
|
||||
typeof M.str[request.component][request.key] === "undefined") {
|
||||
// Try and revive it from local storage.
|
||||
var cached = storage.get('core_str/' + request.key + '/' + request.component + '/' + request.lang);
|
||||
var cached = storage.get(request.cacheKey);
|
||||
if (cached) {
|
||||
if (typeof M.str[request.component] === "undefined") {
|
||||
M.str[request.component] = [];
|
||||
@ -103,25 +106,52 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
|
||||
}
|
||||
deferred.resolve(results);
|
||||
} else {
|
||||
// Something is missing, we might as well load them all.
|
||||
var ajaxrequests = [];
|
||||
var fetchpromises = [];
|
||||
|
||||
// Done handler for ajax call. Must be bound to the current fetchpromise. We do this
|
||||
// to avoid creating a function in a loop.
|
||||
var doneFunc = function(str) {
|
||||
this.resolve(str);
|
||||
};
|
||||
|
||||
var failFunc = function(reason) {
|
||||
this.reject(reason);
|
||||
};
|
||||
|
||||
for (i = 0; i < requests.length; i++) {
|
||||
request = requests[i];
|
||||
|
||||
ajaxrequests.push({
|
||||
methodname: 'core_get_string',
|
||||
args: {
|
||||
stringid: request.key,
|
||||
component: request.component,
|
||||
lang: request.lang,
|
||||
stringparams: []
|
||||
}
|
||||
});
|
||||
// If we ever fetched this string with a promise, reuse it.
|
||||
if (typeof promiseCache[request.cacheKey] !== 'undefined') {
|
||||
fetchpromises.push(promiseCache[request.cacheKey]);
|
||||
} else {
|
||||
// Add this to the list we need to really fetch.
|
||||
var fetchpromise = $.Deferred();
|
||||
|
||||
ajaxrequests.push({
|
||||
methodname: 'core_get_string',
|
||||
args: {
|
||||
stringid: request.key,
|
||||
component: request.component,
|
||||
lang: request.lang,
|
||||
stringparams: []
|
||||
},
|
||||
done: doneFunc.bind(fetchpromise),
|
||||
fail: failFunc.bind(fetchpromise)
|
||||
});
|
||||
|
||||
promiseCache[request.cacheKey] = fetchpromise.promise();
|
||||
fetchpromises.push(promiseCache[request.cacheKey]);
|
||||
}
|
||||
}
|
||||
|
||||
var deferreds = ajax.call(ajaxrequests, true, false);
|
||||
$.when.apply(null, deferreds).done(
|
||||
// Everything might already be queued so we need to check if we have real ajax requests to run.
|
||||
if (ajaxrequests.length > 0) {
|
||||
ajax.call(ajaxrequests, true, false);
|
||||
}
|
||||
|
||||
$.when.apply(null, fetchpromises).done(
|
||||
function() {
|
||||
// Turn the list of arguments (unknown length) into a real array.
|
||||
var i = 0;
|
||||
|
@ -29,21 +29,25 @@ define(['core/mustache',
|
||||
'core/str',
|
||||
'core/notification',
|
||||
'core/url',
|
||||
'core/log',
|
||||
'core/config',
|
||||
'core/localstorage',
|
||||
'core/event',
|
||||
'core/yui',
|
||||
'core/log'
|
||||
],
|
||||
function(mustache, $, ajax, str, notification, coreurl, config, storage, event, Y, Log) {
|
||||
function(mustache, $, ajax, str, notification, coreurl, log, config, storage, event, Y, Log) {
|
||||
|
||||
// Module variables.
|
||||
/** @var {Number} uniqInstances Count of times this constructor has been called. */
|
||||
var uniqInstances = 0;
|
||||
|
||||
/** @var {string[]} templateCache - Cache of already loaded templates */
|
||||
/** @var {String[]} templateCache - Cache of already loaded template strings */
|
||||
var templateCache = {};
|
||||
|
||||
/** @var {Promise[]} templatePromises - Cache of already loaded template promises */
|
||||
var templatePromises = {};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -73,11 +77,9 @@ define(['core/mustache',
|
||||
* @param {string} templateName - should consist of the component and the name of the template like this:
|
||||
* core/menu (lib/templates/menu.mustache) or
|
||||
* tool_bananas/yellow (admin/tool/bananas/templates/yellow.mustache)
|
||||
* @param {Boolean} async If false - this function will not return until the promises are resolved.
|
||||
* @return {Promise} JQuery promise object resolved when the template has been fetched.
|
||||
*/
|
||||
Renderer.prototype.getTemplate = function(templateName, async) {
|
||||
var deferred = $.Deferred();
|
||||
Renderer.prototype.getTemplate = function(templateName) {
|
||||
var parts = templateName.split('/');
|
||||
var component = parts.shift();
|
||||
var name = parts.shift();
|
||||
@ -85,18 +87,17 @@ define(['core/mustache',
|
||||
var searchKey = this.currentThemeName + '/' + templateName;
|
||||
|
||||
// First try request variables.
|
||||
if (searchKey in templateCache) {
|
||||
deferred.resolve(templateCache[searchKey]);
|
||||
return deferred.promise();
|
||||
if (searchKey in templatePromises) {
|
||||
return templatePromises[searchKey];
|
||||
}
|
||||
|
||||
// Now try local storage.
|
||||
var cached = storage.get('core_template/' + searchKey);
|
||||
|
||||
if (cached) {
|
||||
deferred.resolve(cached);
|
||||
templateCache[searchKey] = cached;
|
||||
return deferred.promise();
|
||||
templatePromises[searchKey] = $.Deferred().resolve(cached).promise();
|
||||
return templatePromises[searchKey];
|
||||
}
|
||||
|
||||
// Oh well - load via ajax.
|
||||
@ -107,20 +108,16 @@ define(['core/mustache',
|
||||
template: name,
|
||||
themename: this.currentThemeName
|
||||
}
|
||||
}], async, false);
|
||||
}], true, false);
|
||||
|
||||
promises[0].done(
|
||||
templatePromises[searchKey] = promises[0].then(
|
||||
function(templateSource) {
|
||||
storage.set('core_template/' + searchKey, templateSource);
|
||||
templateCache[searchKey] = templateSource;
|
||||
deferred.resolve(templateSource);
|
||||
}
|
||||
).fail(
|
||||
function(ex) {
|
||||
deferred.reject(ex);
|
||||
storage.set('core_template/' + searchKey, templateSource);
|
||||
return templateSource;
|
||||
}
|
||||
);
|
||||
return deferred.promise();
|
||||
return templatePromises[searchKey];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -132,15 +129,14 @@ define(['core/mustache',
|
||||
* @return {string}
|
||||
*/
|
||||
Renderer.prototype.partialHelper = function(name) {
|
||||
var template = '';
|
||||
|
||||
this.getTemplate(name, false).done(
|
||||
function(source) {
|
||||
template = source;
|
||||
}
|
||||
).fail(notification.exception);
|
||||
var searchKey = this.currentThemeName + '/' + name;
|
||||
|
||||
return template;
|
||||
if (!(searchKey in templateCache)) {
|
||||
notification.exception(new Error('Failed to pre-fetch the template: ' + name));
|
||||
}
|
||||
|
||||
return templateCache[searchKey];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -180,7 +176,8 @@ define(['core/mustache',
|
||||
]
|
||||
};
|
||||
// We forced loading of this early, so it will be in the cache.
|
||||
var template = templateCache[this.currentThemeName + '/core/pix_icon'];
|
||||
var searchKey = this.currentThemeName + '/core/pix_icon';
|
||||
var template = templateCache[searchKey];
|
||||
result = mustache.render(template, templatecontext, this.partialHelper.bind(this));
|
||||
return result.trim();
|
||||
};
|
||||
@ -392,44 +389,29 @@ define(['core/mustache',
|
||||
* @return {Promise} object
|
||||
*/
|
||||
Renderer.prototype.doRender = function(templateSource, context, themeName) {
|
||||
var deferred = $.Deferred();
|
||||
|
||||
this.currentThemeName = themeName;
|
||||
|
||||
// Make sure we fetch this first.
|
||||
var loadPixTemplate = this.getTemplate('core/pix_icon', true);
|
||||
return this.getTemplate('core/pix_icon').then(function() {
|
||||
this.addHelpers(context, themeName);
|
||||
var result = mustache.render(templateSource, context, this.partialHelper.bind(this));
|
||||
|
||||
loadPixTemplate.done(
|
||||
function() {
|
||||
this.addHelpers(context, themeName);
|
||||
var result = '';
|
||||
try {
|
||||
result = mustache.render(templateSource, context, this.partialHelper.bind(this));
|
||||
} catch (ex) {
|
||||
deferred.reject(ex);
|
||||
}
|
||||
if (this.requiredStrings.length > 0) {
|
||||
return str.get_strings(this.requiredStrings).then(function(strings) {
|
||||
|
||||
if (this.requiredStrings.length > 0) {
|
||||
str.get_strings(this.requiredStrings)
|
||||
.then(function(strings) {
|
||||
// Why do we not do another call the render here?
|
||||
//
|
||||
// Because that would expose DOS holes. E.g.
|
||||
// I create an assignment called "{{fish" which
|
||||
// would get inserted in the template in the first pass
|
||||
// and cause the template to die on the second pass (unbalanced).
|
||||
|
||||
// Why do we not do another call the render here?
|
||||
//
|
||||
// Because that would expose DOS holes. E.g.
|
||||
// I create an assignment called "{{fish" which
|
||||
// would get inserted in the template in the first pass
|
||||
// and cause the template to die on the second pass (unbalanced).
|
||||
|
||||
result = this.treatStringsInContent(result, strings);
|
||||
deferred.resolve(result, this.getJS(strings));
|
||||
}.bind(this))
|
||||
.fail(deferred.reject);
|
||||
} else {
|
||||
deferred.resolve(result.trim(), this.getJS([]));
|
||||
}
|
||||
}.bind(this)
|
||||
).fail(deferred.reject);
|
||||
return deferred.promise();
|
||||
result = this.treatStringsInContent(result, strings);
|
||||
return $.Deferred().resolve(result, this.getJS(strings)).promise();
|
||||
}.bind(this));
|
||||
} else {
|
||||
return $.Deferred().resolve(result.trim(), this.getJS([])).promise();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -486,6 +468,66 @@ define(['core/mustache',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Scan a template source for partial tags and return a list of the found partials.
|
||||
*
|
||||
* @method scanForPartials
|
||||
* @private
|
||||
* @param {string} templateSource - source template to scan.
|
||||
* @return {Array} List of partials.
|
||||
*/
|
||||
Renderer.prototype.scanForPartials = function(templateSource) {
|
||||
var tokens = mustache.parse(templateSource),
|
||||
partials = [];
|
||||
|
||||
var findPartial = function(tokens, partials) {
|
||||
var i, token;
|
||||
for (i = 0; i < tokens.length; i++) {
|
||||
token = tokens[i];
|
||||
if (token[0] == '>' || token[0] == '<') {
|
||||
partials.push(token[1]);
|
||||
}
|
||||
if (token.length > 4) {
|
||||
findPartial(token[4], partials);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
findPartial(tokens, partials);
|
||||
|
||||
return partials;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a template and scan it for partials. Recursively fetch the partials.
|
||||
*
|
||||
* @method cachePartials
|
||||
* @private
|
||||
* @param {string} templateName - should consist of the component and the name of the template like this:
|
||||
* core/menu (lib/templates/menu.mustache) or
|
||||
* tool_bananas/yellow (admin/tool/bananas/templates/yellow.mustache)
|
||||
* @return {Promise} JQuery promise object resolved when all partials are in the cache.
|
||||
*/
|
||||
Renderer.prototype.cachePartials = function(templateName) {
|
||||
return this.getTemplate(templateName).then(function(templateSource) {
|
||||
var i;
|
||||
var partials = this.scanForPartials(templateSource);
|
||||
var fetchThemAll = [];
|
||||
|
||||
for (i = 0; i < partials.length; i++) {
|
||||
var searchKey = this.currentThemeName + '/' + partials[i];
|
||||
if (searchKey in templatePromises) {
|
||||
continue;
|
||||
}
|
||||
fetchThemAll.push(this.cachePartials(partials[i]));
|
||||
}
|
||||
|
||||
return $.when.apply($, fetchThemAll).then(function() {
|
||||
return templateSource;
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a template and call doRender on it.
|
||||
*
|
||||
@ -499,8 +541,6 @@ define(['core/mustache',
|
||||
* @return {Promise} JQuery promise object resolved when the template has been rendered.
|
||||
*/
|
||||
Renderer.prototype.render = function(templateName, context, themeName) {
|
||||
var deferred = $.Deferred();
|
||||
|
||||
if (typeof (themeName) === "undefined") {
|
||||
// System context by default.
|
||||
themeName = config.theme;
|
||||
@ -508,28 +548,9 @@ define(['core/mustache',
|
||||
|
||||
this.currentThemeName = themeName;
|
||||
|
||||
var loadTemplate = this.getTemplate(templateName, true);
|
||||
|
||||
loadTemplate.done(
|
||||
function(templateSource) {
|
||||
var renderPromise = this.doRender(templateSource, context, themeName);
|
||||
|
||||
renderPromise.done(
|
||||
function(result, js) {
|
||||
deferred.resolve(result, js);
|
||||
}
|
||||
).fail(
|
||||
function(ex) {
|
||||
deferred.reject(ex);
|
||||
}
|
||||
);
|
||||
}.bind(this)
|
||||
).fail(
|
||||
function(ex) {
|
||||
deferred.reject(ex);
|
||||
}
|
||||
);
|
||||
return deferred.promise();
|
||||
return this.cachePartials(templateName).then(function(templateSource) {
|
||||
return this.doRender(templateSource, context, themeName);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user