diff --git a/lib/amd/build/str.min.js b/lib/amd/build/str.min.js index 30589a89ea9..e2d06e48584 100644 --- a/lib/amd/build/str.min.js +++ b/lib/amd/build/str.min.js @@ -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()}}}); \ No newline at end of file +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)};for(i=0;i<e.length;i++)if(f=e[i],"undefined"!=typeof d[f.cacheKey])m.push(d[f.cacheKey]);else{var o=a.Deferred();l.push({methodname:"core_get_string",args:{stringid:f.key,component:f.component,lang:f.lang,stringparams:[]},done:n.bind(o)}),d[f.cacheKey]=o.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()}}}); \ No newline at end of file diff --git a/lib/amd/src/str.js b/lib/amd/src/str.js index ad14a0af26e..6e9407b277c 100644 --- a/lib/amd/src/str.js +++ b/lib/amd/src/str.js @@ -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,47 @@ 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); + }; 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) + }); + + 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;