MDL-53667 tool_lp: Use event delegate for competency dialogue

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.
This commit is contained in:
Frederic Massart 2016-04-14 17:47:02 +08:00
parent d580b62fb3
commit e912927d7b
8 changed files with 56 additions and 59 deletions

View File

@ -1 +1 @@
define(["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/dialogue"],function(a,b,c,d,e,f){var g=function(b){this.options={includerelated:!1,includecourses:!1},a.extend(this.options,b)};return g.prototype.triggerCompetencyViewedEvent=function(a){c.call([{methodname:"core_competency_competency_viewed",args:{id:a}}])},g.prototype.enhanceDialogue=function(a){var b=new g({includerelated:!1});b.watch(a.getContent())},g.prototype.showDialogue=function(a){var c=this.getCompetencyDataPromise(a),e=this;c.done(function(c){d.render("tool_lp/competency_summary",c).done(function(b){e.triggerCompetencyViewedEvent(a),new f(c.competency.shortname,b,e.enhanceDialogue)}).fail(b.exception)}).fail(b.exception)},g.prototype.showDialogueFromData=function(a){var c=this;d.render("tool_lp/competency_summary",a).done(function(b){c.triggerCompetencyViewedEvent(a.id),new f(a.shortname,b,c.enhanceDialogue)}).fail(b.exception)},g.prototype.clickEventHandler=function(b){var c=b.data.compdialogue,d=a(b.currentTarget).data("id");c.showDialogue(d),b.preventDefault()},g.prototype.getCompetencyDataPromise=function(a){var d=c.call([{methodname:"tool_lp_data_for_competency_summary",args:{competencyid:a,includerelated:this.options.includerelated,includecourses:this.options.includecourses}}]);return d[0].then(function(a){return a}).fail(b.exception)},g.prototype.watch=function(b){a(b).off("click",'[data-action="competency-dialogue"]',this.clickEventHandler),a(b).on("click",'[data-action="competency-dialogue"]',{compdialogue:this},this.clickEventHandler)},g});
define(["jquery","core/notification","core/ajax","core/templates","core/str","tool_lp/dialogue"],function(a,b,c,d,e,f){var g,h=function(){};return h.prototype.triggerCompetencyViewedEvent=function(a){c.call([{methodname:"core_competency_competency_viewed",args:{id:a}}])},h.prototype.showDialogue=function(a,c){var e=this.getCompetencyDataPromise(a,c),g=this;e.done(function(c){d.render("tool_lp/competency_summary",c).done(function(b){g.triggerCompetencyViewedEvent(a),new f(c.competency.shortname,b)}).fail(b.exception)}).fail(b.exception)},h.prototype.showDialogueFromData=function(a){var c=this;d.render("tool_lp/competency_summary",a).done(function(b){c.triggerCompetencyViewedEvent(a.id),new f(a.shortname,b,c.enhanceDialogue)}).fail(b.exception)},h.prototype.clickEventHandler=function(b){var c=b.data.compdialogue,d=a(b.currentTarget),e=d.data("id"),f=!d.data("excluderelated"),g=d.data("includecourses");c.showDialogue(e,{includerelated:f,includecourses:g}),b.preventDefault()},h.prototype.getCompetencyDataPromise=function(a,d){var e=c.call([{methodname:"tool_lp_data_for_competency_summary",args:{competencyid:a,includerelated:d.includerelated||!1,includecourses:d.includecourses||!1}}]);return e[0].then(function(a){return a}).fail(b.exception)},{init:function(){"undefined"==typeof g&&(g=new h,a("body").delegate('[data-action="competency-dialogue"]',"click",{compdialogue:g},g.clickEventHandler.bind(g)))}}});

View File

@ -1 +1 @@
define(["jquery","core/notification","tool_lp/dialogue","core/str","core/ajax","core/templates"],function(a,b,c,d,e,f){var g=function(b){a(b).on("click",this.configureSettings.bind(this))};return g.prototype._dialogue=null,g.prototype.configureSettings=function(e){var g=a(e.target).closest("a").data("courseid"),h=a(e.target).closest("a").data("pushratingstouserplans"),i={courseid:g,settings:{pushratingstouserplans:h}};e.preventDefault(),f.render("tool_lp/course_competency_settings",i).done(function(a){d.get_string("configurecoursecompetencysettings","tool_lp").done(function(b){this._dialogue=new c(b,a,this.addListeners.bind(this))}.bind(this)).fail(b.exception)}.bind(this)).fail(b.exception)},g.prototype.addListeners=function(){var a=this._find('[data-action="save"]');a.on("click",this.saveSettings.bind(this));var b=this._find('[data-action="cancel"]');b.on("click",this.cancelChanges.bind(this))},g.prototype.cancelChanges=function(a){a.preventDefault(),this._dialogue.close()},g.prototype._find=function(b){return a('[data-region="coursecompetencysettings"]').find(b)},g.prototype.saveSettings=function(a){a.preventDefault();var c=this._find('input[name="pushratingstouserplans"]:checked').val(),d=this._find('input[name="courseid"]').val(),f={pushratingstouserplans:c};e.call([{methodname:"core_competency_update_course_competency_settings",args:{courseid:d,settings:f}}])[0].done(function(){this.refreshCourseCompetenciesPage()}.bind(this)).fail(b.exception)},g.prototype.refreshCourseCompetenciesPage=function(){var c=this._find('input[name="courseid"]').val();e.call([{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:c}}])[0].done(function(c){f.render("tool_lp/course_competencies_page",c).done(function(b,c){a('[data-region="coursecompetenciespage"]').replaceWith(b),f.runTemplateJS(c),this._dialogue.close()}.bind(this)).fail(b.exception)}.bind(this)).fail(b.exception)},g});
define(["jquery","core/notification","tool_lp/dialogue","core/str","core/ajax","core/templates"],function(a,b,c,d,e,f){var g=function(b){a(b).on("click",this.configureSettings.bind(this))};return g.prototype._dialogue=null,g.prototype.configureSettings=function(e){var g=a(e.target).closest("a").data("courseid"),h=a(e.target).closest("a").data("pushratingstouserplans"),i={courseid:g,settings:{pushratingstouserplans:h}};e.preventDefault(),f.render("tool_lp/course_competency_settings",i).done(function(a){d.get_string("configurecoursecompetencysettings","tool_lp").done(function(b){this._dialogue=new c(b,a,this.addListeners.bind(this))}.bind(this)).fail(b.exception)}.bind(this)).fail(b.exception)},g.prototype.addListeners=function(){var a=this._find('[data-action="save"]');a.on("click",this.saveSettings.bind(this));var b=this._find('[data-action="cancel"]');b.on("click",this.cancelChanges.bind(this))},g.prototype.cancelChanges=function(a){a.preventDefault(),this._dialogue.close()},g.prototype._find=function(b){return a('[data-region="coursecompetencysettings"]').find(b)},g.prototype.saveSettings=function(a){a.preventDefault();var c=this._find('input[name="pushratingstouserplans"]:checked').val(),d=this._find('input[name="courseid"]').val(),f={pushratingstouserplans:c};e.call([{methodname:"core_competency_update_course_competency_settings",args:{courseid:d,settings:f}}])[0].done(function(){this.refreshCourseCompetenciesPage()}.bind(this)).fail(b.exception)},g.prototype.refreshCourseCompetenciesPage=function(){var c=this._find('input[name="courseid"]').val();e.call([{methodname:"tool_lp_data_for_course_competencies_page",args:{courseid:c}}])[0].done(function(c){f.render("tool_lp/course_competencies_page",c).done(function(b,c){a('[data-region="coursecompetenciespage"]').replaceWith(b),f.runTemplateJS(c),this._dialogue.close()}.bind(this)).fail(b.exception)}.bind(this)).fail(b.exception)},g});

View 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 */ {
return Competencydialogue;
/**
* Initialise the competency dialogue module.
*
* Only the first call matters.
*
* @return {Void}
*/
init: function() {
if (typeof instance !== 'undefined') {
return;
}
// 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));
}
};
});

View 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}}

View 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}}

View 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}}

View File

@ -110,7 +110,7 @@
<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}}
@ -119,7 +119,7 @@
<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}}
@ -131,7 +131,7 @@
<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}}
@ -145,7 +145,7 @@
<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}}
@ -159,8 +159,7 @@
</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}}

View 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]'));