MDL-53667 tool_lp: Use event delegate for competency dialogue
authorFrederic Massart <fred@moodle.com>
Thu, 14 Apr 2016 09:47:02 +0000 (17:47 +0800)
committerFrederic Massart <fred@moodle.com>
Mon, 18 Apr 2016 06:52:48 +0000 (14:52 +0800)
This was causing dramatical performance issues when the module
was loaded hundreds of times on the same page, causing each instance
to detach and attach a new event listener.

admin/tool/lp/amd/build/competencydialogue.min.js
admin/tool/lp/amd/build/course_competency_settings.min.js
admin/tool/lp/amd/src/competencydialogue.js
admin/tool/lp/templates/competency_path.mustache
admin/tool/lp/templates/related_competencies.mustache
admin/tool/lp/templates/user_evidence_page.mustache
admin/tool/lpmigrate/templates/migrate_frameworks_results.mustache
report/competency/templates/report.mustache

index b22cdb3..2ef99e4 100644 (file)
Binary files a/admin/tool/lp/amd/build/competencydialogue.min.js and b/admin/tool/lp/amd/build/competencydialogue.min.js differ
index 1b1b540..5fe246e 100644 (file)
Binary files a/admin/tool/lp/amd/build/course_competency_settings.min.js and b/admin/tool/lp/amd/build/course_competency_settings.min.js differ
index 747b9b0..affcea6 100644 (file)
@@ -29,18 +29,20 @@ define(['jquery',
         'tool_lp/dialogue'],
        function($, notification, ajax, templates, str, Dialogue) {
 
+    /**
+     * The main instance we'll be working with.
+     *
+     * @type {Competencydialogue}
+     */
+    var instance;
+
     /**
      * Constructor for CompetencyDialogue.
      *
      * @param {Object} options
      *
      */
-    var Competencydialogue = function(options) {
-        this.options = {
-            includerelated: false,
-            includecourses: false
-        };
-        $.extend(this.options, options);
+    var Competencydialogue = function() {
     };
 
     /**
@@ -56,29 +58,16 @@ define(['jquery',
         }]);
     };
 
-    /**
-     * Callback on dialogue display, it apply enhance on competencies dialogue.
-     *
-     * @param {Dialogue} dialogue
-     * @method enhanceDialogue
-     */
-    Competencydialogue.prototype.enhanceDialogue = function(dialogue) {
-        //Apply watch on the related competencies and competencies in the dialogue.
-        var comprelated = new Competencydialogue({includerelated : false});
-        comprelated.watch(dialogue.getContent());
-    };
-
     /**
      * Display a dialogue box by competencyid.
      *
-     * @param {Number} the competency id
-     * @param {Object} Options for tool_lp_data_for_competency_summary service
-     * @param {Object} dataSource data to be used to display dialogue box
+     * @param {Number} competencyid The competency ID.
+     * @param {Object} options The options.
      * @method showDialogue
      */
-    Competencydialogue.prototype.showDialogue = function(competencyid) {
+    Competencydialogue.prototype.showDialogue = function(competencyid, options) {
 
-        var datapromise = this.getCompetencyDataPromise(competencyid);
+        var datapromise = this.getCompetencyDataPromise(competencyid, options);
         var localthis = this;
         datapromise.done(function(data) {
             // Inner Html in the dialogue content.
@@ -90,8 +79,7 @@ define(['jquery',
                     // Show the dialogue.
                     new Dialogue(
                         data.competency.shortname,
-                        html,
-                        localthis.enhanceDialogue
+                        html
                     );
                 }).fail(notification.exception);
         }).fail(notification.exception);
@@ -130,10 +118,16 @@ define(['jquery',
     Competencydialogue.prototype.clickEventHandler = function(e) {
 
         var compdialogue = e.data.compdialogue;
-        var competencyid = $(e.currentTarget).data('id');
+        var currentTarget = $(e.currentTarget);
+        var competencyid = currentTarget.data('id');
+        var includerelated = !(currentTarget.data('excluderelated'));
+        var includecourses = currentTarget.data('includecourses');
 
         // Show the dialogue box.
-        compdialogue.showDialogue(competencyid);
+        compdialogue.showDialogue(competencyid, {
+            includerelated: includerelated,
+            includecourses: includecourses
+        });
         e.preventDefault();
     };
 
@@ -144,13 +138,13 @@ define(['jquery',
      * @return {Promise} return promise on data request
      * @method getCompetencyDataPromise
      */
-    Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid) {
+    Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid, options) {
 
         var requests = ajax.call([
             { methodname: 'tool_lp_data_for_competency_summary',
               args: { competencyid: competencyid,
-                      includerelated: this.options.includerelated,
-                      includecourses: this.options.includecourses
+                      includerelated: options.includerelated || false,
+                      includecourses: options.includecourses || false
                     }
             }
         ]);
@@ -160,16 +154,24 @@ define(['jquery',
         }).fail(notification.exception);
     };
 
-    /**
-     * Watch the competencies links in container.
-     *
-     * @param {String} container selector of node containing competencies links
-     * @method watch
-     */
-    Competencydialogue.prototype.watch = function(containerSelector) {
-        $(containerSelector).off('click', '[data-action="competency-dialogue"]', this.clickEventHandler);
-        $(containerSelector).on('click', '[data-action="competency-dialogue"]', { compdialogue: this }, this.clickEventHandler);
-    };
+    return /** @alias module:tool_lp/competencydialogue */ {
+
+        /**
+         * Initialise the competency dialogue module.
+         *
+         * Only the first call matters.
+         *
+         * @return {Void}
+         */
+        init: function() {
+            if (typeof instance !== 'undefined') {
+                return;
+            }
 
-    return Competencydialogue;
+            // Instantiate the one instance and delegate event on the body.
+            instance = new Competencydialogue();
+            $('body').delegate('[data-action="competency-dialogue"]', 'click', { compdialogue: instance },
+                instance.clickEventHandler.bind(instance));
+        }
+    };
 });
index 8cb1a55..01e21c6 100644 (file)
@@ -49,7 +49,6 @@
 </nav>
 {{#js}}
 require(['tool_lp/competencydialogue'], function(Compdialogue) {
-    var competencydialogue = new Compdialogue({includerelated : true});
-    competencydialogue.watch('[id="competency-path-{{uniqid}}"]');
+    Compdialogue.init();
 });
 {{/js}}
index 897a26e..f9b2c51 100644 (file)
@@ -24,7 +24,6 @@
 </div>
 {{#js}}
 require(['tool_lp/competencydialogue'], function(Compdialogue) {
-    var competencydialogue = new Compdialogue({includerelated : true});
-    competencydialogue.watch('[data-region="relatedcompetencies"]');
+    Compdialogue.init();
 });
 {{/js}}
index 7e873f3..1862a1d 100644 (file)
@@ -109,8 +109,7 @@ require(['tool_lp/user_evidence_actions'], function(UserEvidenceActions) {
 
 {{#js}}
 require(['tool_lp/competencydialogue'], function(Compdialogue) {
-    var competencydialogue = new Compdialogue({includerelated : true});
-    competencydialogue.watch('[data-region="user-evidence-competencies"]');
+    Compdialogue.init();
 });
 {{/js}}
 
index fc6e074..a5527c2 100644 (file)
     <h4>{{#str}}unmappedin, tool_lpmigrate, {{frameworkfrom.shortname}}{{/str}}</h4>
     <ul>
         {{#unmappedfrom}}
-            <li><a href="#" data-id="{{id}}" data-action="competency-dialogue">{{shortname}}</a> <em>{{idnumber}}</em></li>
+            <li><a href="#" data-id="{{id}}" data-action="competency-dialogue" data-includecourses="true">{{shortname}}</a> <em>{{idnumber}}</em></li>
         {{/unmappedfrom}}
     </ul>
     {{/hasunmappedfrom}}
     <h4>{{#str}}unmappedin, tool_lpmigrate, {{frameworkto.shortname}}{{/str}}</h4>
     <ul>
         {{#unmappedto}}
-            <li><a href="#" data-id="{{id}}" data-action="competency-dialogue">{{shortname}}</a> <em>{{idnumber}}</em></li>
+            <li><a href="#" data-id="{{id}}" data-action="competency-dialogue" data-includecourses="true">{{shortname}}</a> <em>{{idnumber}}</em></li>
         {{/unmappedto}}
     </ul>
     {{/hasunmappedto}}
             <li>
                 <p>
                     {{message}}<br>
-                    <small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue">{{competency}}</a></small>
+                    <small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue" data-includecourses="true">{{competency}}</a></small>
                 </p>
             </li>
         {{/warnings}}
             <li>
                 <p>
                     {{message}}<br>
-                    <small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue">{{competency}}</a></small>
+                    <small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue" data-includecourses="true">{{competency}}</a></small>
                 </p>
             </li>
         {{/errors}}
     </p>
 </div>
 {{#js}}
-require(['tool_lp/competencydialogue'], function(CompDialogue) {
-    var cd = new CompDialogue({includecourses: true, includerelated: true});
-    cd.watch('[data-region="migration-results"]');
-})
+require(['tool_lp/competencydialogue'], function(Compdialogue) {
+    Compdialogue.init();
+});
 {{/js}}
index f025468..1c6979e 100644 (file)
@@ -51,8 +51,7 @@
 </div>
 {{#js}}
 require(['tool_lp/competencydialogue'], function(Compdialogue) {
-    var competencydialogue = new Compdialogue({includerelated : true});
-    competencydialogue.watch('[data-region="competency-breakdown-report"]');
+    Compdialogue.init();
 });
 require(['report_competency/grading_popup'], function(Popup) {
     (new Popup('[data-region=competency-breakdown-report]', '[data-user-competency=true]'));