From abca4753b499e453b3d61ddbb6ddc1d802c56086 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 24 Oct 2018 07:59:25 +0800 Subject: [PATCH 1/3] MDL-63714 javascript: Improve docs for pendingjs --- lib/javascript-static.js | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/javascript-static.js b/lib/javascript-static.js index 444aab5a781..a4296ee3aca 100644 --- a/lib/javascript-static.js +++ b/lib/javascript-static.js @@ -653,16 +653,22 @@ M.util.complete_js = []; /** * Register any long running javascript code with a unique identifier. - * Should be followed with a call to js_complete with a matching - * idenfitier when the code is complete. May also be called with no arguments - * to test if there is any js calls pending. This is relied on by behat so that - * it can wait for all pending updates before interacting with a page. - * @param String uniqid - optional, if provided, - * registers this identifier until js_complete is called. - * @return boolean - True if there is any pending js. + * This is used to ensure that Behat steps do not continue with interactions until the page finishes loading. + * + * All calls to M.util.js_pending _must_ be followed by a subsequent call to M.util.js_complete with the same exact + * uniqid. + * + * This function may also be called with no arguments to test if there is any js calls pending. + * + * The uniqid specified may be any Object, including Number, String, or actual Object; however please note that the + * paired js_complete function performs a strict search for the key specified. As such, if using an Object, the exact + * Object must be passed into both functions. + * + * @param {Mixed} uniqid Register long-running code against the supplied identifier + * @return {Number} Number of pending items */ M.util.js_pending = function(uniqid) { - if (uniqid !== false) { + if (typeof uniqid !== 'undefined') { M.util.pending_js.push(uniqid); } @@ -690,11 +696,12 @@ YUI.add('moodle-core-io', function(Y) { }); /** - * Unregister any long running javascript code by unique identifier. - * This function should form a matching pair with js_pending + * Unregister some long running javascript code using the unique identifier specified in M.util.js_pending. * - * @param String uniqid - required, unregisters this identifier - * @return boolean - True if there is any pending js. + * This function must be matched with an identical call to M.util.js_pending. + * + * @param {Mixed} uniqid Register long-running code against the supplied identifier + * @return {Number} Number of pending items remaining after removing this item */ M.util.js_complete = function(uniqid) { // Use the Y.Array.indexOf instead of the native because some older browsers do not support @@ -702,6 +709,8 @@ M.util.js_complete = function(uniqid) { var index = Y.Array.indexOf(M.util.pending_js, uniqid); if (index >= 0) { M.util.complete_js.push(M.util.pending_js.splice(index, 1)); + } else { + window.console.log("Unable to locate key for js_complete call", uniqid); } return M.util.pending_js.length; From 527f895e93ae5a59b876c30ea00947941f1c4646 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 19 Oct 2018 15:13:37 +0800 Subject: [PATCH 2/3] MDL-63714 core: Wrap doRender in pendingjs --- lib/amd/build/templates.min.js | 2 +- lib/amd/src/templates.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/amd/build/templates.min.js b/lib/amd/build/templates.min.js index f85887e767d..7df3db35413 100644 --- a/lib/amd/build/templates.min.js +++ b/lib/amd/build/templates.min.js @@ -1 +1 @@ -define(["core/mustache","jquery","core/ajax","core/str","core/notification","core/url","core/config","core/localstorage","core/icon_system","core/event","core/yui","core/log","core/truncate","core/user_date"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){var o=0,p={},q={},r={},s={},t=function(){this.requiredStrings=[],this.requiredJS=[],this.requiredDates=[],this.currentThemeName=""};t.prototype.requiredStrings=null,t.prototype.requiredDates=[],t.prototype.requiredJS=null,t.prototype.currentThemeName="",t.prototype.getTemplate=function(a){var d=a.split("/"),e=d.shift(),f=d.shift(),g=this.currentThemeName+"/"+a;if(g in q)return q[g];var i=h.get("core_template/"+g);if(i)return p[g]=i,q[g]=b.Deferred().resolve(i).promise(),q[g];var j=c.call([{methodname:"core_output_load_template",args:{component:e,template:f,themename:this.currentThemeName}}],!0,!1);return q[g]=j[0].then(function(a){return p[g]=a,h.set("core_template/"+g,a),a}),q[g]},t.prototype.partialHelper=function(a){var b=this.currentThemeName+"/"+a;return b in p||e.exception(new Error("Failed to pre-fetch the template: "+a)),p[b]},t.prototype.renderIcon=function(a,c,d){var f=g.iconsystemmodule,h=b.Deferred();return require([f],function(a){var b=new a;b instanceof i?(s=b,b.init().then(h.resolve)["catch"](e.exception)):h.reject("Invalid icon system specified"+g.iconsystemmodule)}),h.then(function(a){return this.getTemplate(a.getTemplateName())}.bind(this)).then(function(b){return s.renderIcon(a,c,d,b)})},t.prototype.pixHelper=function(a,b,c){var d=b.split(","),e="",f="",g="";d.length>0&&(e=c(d.shift().trim(),a)),d.length>0&&(f=c(d.shift().trim(),a)),d.length>0&&(g=c(d.join(",").trim(),a));var h=s.getTemplateName(),i=this.currentThemeName+"/"+h,j=p[i];return e=e.replace(///gi,"/"),s.renderIcon(e,f,g,j)},t.prototype.jsHelper=function(a,b,c){return this.requiredJS.push(c(b,a)),""},t.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+"]]"},t.prototype.quoteHelper=function(a,b,c){var d=c(b.trim(),a);return d=d.replace('"','\\"').replace(/([\{\}]{2,3})/g,"{{=<% %>=}}$1<%={{ }}=%>"),'"'+d+'"'},t.prototype.shortenTextHelper=function(a,b,c){var d=/(.*?),(.*)/,e=b.match(d),f=e[1].trim(),g=e[2].trim(),h=c(g,a);return m.truncate(h,{length:f,words:!0,ellipsis:"..."})},t.prototype.userDateHelper=function(a,b,c){var d=/(.*?),(.*)/,e=b.match(d),f=c(e[1].trim(),a),g=c(e[2].trim(),a),h=this.requiredDates.length;return this.requiredDates.push({timestamp:f,format:g}),"[[_t_"+h+"]]"},t.prototype.addHelpers=function(a,b){this.currentThemeName=b,this.requiredStrings=[],this.requiredJS=[],a.uniqid=o++,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.shortentext=function(){return this.shortenTextHelper.bind(this,a)}.bind(this),a.userdate=function(){return this.userDateHelper.bind(this,a)}.bind(this),a.globals={config:g},a.currentTheme=b},t.prototype.getJS=function(){var a="";return this.requiredJS.length>0&&(a=this.requiredJS.join(";\n")),a},t.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},t.prototype.treatDatesInContent=function(a,b){return b.forEach(function(b,c){var d="\\[\\[_t_"+c+"\\]\\]",e=new RegExp(d,"g");a=a.replace(e,b)}),a},t.prototype.doRender=function(c,e,f){this.currentThemeName=f;var g=s.getTemplateName();return this.getTemplate(g).then(function(){this.addHelpers(e,f);var d=a.render(c,e,this.partialHelper.bind(this));return b.Deferred().resolve(d.trim(),this.getJS()).promise()}.bind(this)).then(function(a,c){return this.requiredStrings.length>0?d.get_strings(this.requiredStrings).then(function(d){return this.requiredDates=this.requiredDates.map(function(a){return{timestamp:this.treatStringsInContent(a.timestamp,d),format:this.treatStringsInContent(a.format,d)}}.bind(this)),a=this.treatStringsInContent(a,d),c=this.treatStringsInContent(c,d),b.Deferred().resolve(a,c).promise()}.bind(this)):b.Deferred().resolve(a,c).promise()}.bind(this)).then(function(a,c){return this.requiredDates.length>0?n.get(this.requiredDates).then(function(d){return a=this.treatDatesInContent(a,d),c=this.treatDatesInContent(c,d),b.Deferred().resolve(a,c).promise()}.bind(this)):b.Deferred().resolve(a,c).promise()}.bind(this))};var u=function(a){if(""!==a.trim()){var c=b("