mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
MDL-50308 tool_lp: Big javascript cleanup
This includes: * Move all JS modules from lib/amd to admin/tool/lp/amd * Add all jsdocs * fix all jshint warnings * Rewrite the actionmenu wrapper to a real amd module
This commit is contained in:
parent
d629323f72
commit
7e8d4dac9b
41 changed files with 1805 additions and 398 deletions
1
admin/tool/lp/amd/build/competencies.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/competencies.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
admin/tool/lp/amd/build/competencyactions.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/competencyactions.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
admin/tool/lp/amd/build/competencytree.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/competencytree.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["core/ajax","core/notification","jquery"],function(a,b,c){var d=[],e=0,f=function(b){var f=c.Deferred();b="";var g=a.call([{methodname:"tool_lp_search_competencies",args:{searchtext:b,competencyframeworkid:e}}]);return g[0].done(function(a){d=[];var b=0;for(b=0;b<a.length;b++)d[a[b].id]=a[b];f.resolve(d)}).fail(function(a){f.reject(a)}),f.promise()};return{init:function(a){e=a,f("").fail(b.exception)},getCompetencyFrameworkId:function(){return e},getCompetency:function(a){return d[a]},listCompetencies:function(){return d},applySearch:function(a){return f(a)}}});
|
1
admin/tool/lp/amd/build/coursecompetencies.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/coursecompetencies.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
admin/tool/lp/amd/build/dialogue.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/dialogue.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["core/yui"],function(a){var b=function(b,c,d){this.yuiDialogue=null;var e=this;a.use("moodle-core-notification",function(){e.yuiDialogue=new M.core.dialogue({headerContent:b,bodyContent:c,draggable:!0,visible:!1,center:!0,modal:!0}),e.yuiDialogue.after("visibleChange",function(a){a.newVal&&d(e)}),e.yuiDialogue.show()})};return b.prototype.close=function(){this.yuiDialogue.hide(),this.yuiDialogue.destroy()},b.prototype.getContent=function(){return this.yuiDialogue.bodyNode.getDOMNode()},b});
|
1
admin/tool/lp/amd/build/dragdrop-reorder.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/dragdrop-reorder.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["core/str","core/yui"],function(a,b){var c=function(a){var b=a.drag.get("node"),c=a.drop.get("node");this.callback(b.getDOMNode(),c.getDOMNode())};return{dragdrop:function(d,e,f,g,h,i,j,k){a.get_strings([{key:"emptydragdropregion",component:"moodle"},{key:"movecontent",component:"moodle"},{key:"tocontent",component:"moodle"}]).done(function(){b.use("moodle-tool_lp-dragdrop-reorder",function(){var a={callback:k};M.tool_lp.dragdrop_reorder({group:d,dragHandleText:e,sameNodeText:f,parentNodeText:g,sameNodeClass:h,parentNodeClass:i,dragHandleInsertClass:j,callback:b.bind(c,a)})})})}}});
|
|
@ -1 +1 @@
|
|||
define(["jquery","core/templates","core/ajax","core/notification"],function(a,b,c,d){var e=0,f=function(c,d){a('[data-region="managecompetencies"]').replaceWith(c),b.runTemplateJS(d)},g=function(a){b.render("tool_lp/manage_competency_frameworks_page",a).done(f).fail(d.exception)},h=function(){var a=c.call([{methodname:"tool_lp_delete_competency_framework",args:{id:e}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:[]}]);a[1].done(g).fail(d.exception)},i=function(b){b.preventDefault();var c=a(this).attr("data-frameworkid");e=c,d.confirm("Confirm",'Delete competency framework "blah"?',"Delete","Cancel",h)};return{init:function(){a('[data-region="managecompetencies"]').on("click",'[data-action="deletecompetencyframework"]',i)}}});
|
||||
define(["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=function(c,d){a('[data-region="managecompetencies"]').replaceWith(c),b.runTemplateJS(d)},h=function(a){b.render("tool_lp/manage_competency_frameworks_page",a).done(g).fail(d.exception)},i=function(){var a=c.call([{methodname:"tool_lp_delete_competency_framework",args:{id:f}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:[]}]);a[1].done(h).fail(d.exception)},j=function(b){b.preventDefault();var g=a(this).attr("data-frameworkid");f=g;var h=c.call([{methodname:"tool_lp_read_competency_framework",args:{id:f}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"tool_lp"},{key:"deletecompetencyframework",component:"tool_lp",param:a.shortname},{key:"delete",component:"tool_lp"},{key:"cancel",component:"tool_lp"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],i)}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:j}});
|
2
admin/tool/lp/amd/build/frameworkmove.min.js
vendored
2
admin/tool/lp/amd/build/frameworkmove.min.js
vendored
|
@ -1 +1 @@
|
|||
define(["core/dragdrop-reorder","core/str","core/notification","jquery","core/ajax"],function(a,b,c,d,e){var f=function(a,b){var f=d(a).data("frameworkid"),g=d(b).data("frameworkid"),h=e.call([{methodname:"tool_lp_reorder_competency_framework",args:{from:f,to:g}}]);h[0].fail(c.exception)};return{init:function(){b.get_string("movecompetencyframework","tool_lp").done(function(b){a.dragdrop("movecompetencyframework",b,{identifier:"movecompetencyframework",component:"tool_lp"},{identifier:"movecompetencyframeworkafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",f)}).fail(c.exception)}}});
|
||||
define(["jquery","core/str","core/notification","core/ajax","tool_lp/dragdrop-reorder"],function(a,b,c,d,e){var f=function(b,e){var f=a(b).data("frameworkid"),g=a(e).data("frameworkid"),h=d.call([{methodname:"tool_lp_reorder_competency_framework",args:{from:f,to:g}}]);h[0].fail(c.exception)};return{init:function(){b.get_string("movecompetencyframework","tool_lp").done(function(a){e.dragdrop("movecompetencyframework",a,{identifier:"movecompetencyframework",component:"tool_lp"},{identifier:"movecompetencyframeworkafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",f)}).fail(c.exception)}}});
|
1
admin/tool/lp/amd/build/menu.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/menu.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["jquery","core/templates","core/notification","core/yui"],function(a,b,c,d){var e=function(b){var c=a(b);c.find("li a").each(function(b,c){a(c).addClass("menu-action"),a(c).attr("role","menuitem")}),a(this).replaceWith(c),d.use("moodle-core-actionmenu",function(){if(null===M.core.actionmenu.instance)M.core.actionmenu.init();else{var a=d.one(c.get(0));M.core.actionmenu.newDOMNode(a.ancestor())}})};return{menu:function(d,f){a(f).each(function(f,g){var h=[];a(g).find("li").each(function(b,c){h.push(a(c).html().trim())});var i={triggerMessage:d,links:h},j=a.proxy(e,g);b.render("core/menu",i).done(j).fail(c.exception)})}}});
|
1
admin/tool/lp/amd/build/menubar.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/menubar.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
admin/tool/lp/amd/build/plandelete.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/plandelete.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=0,h=function(c,d){a('[data-region="plans"]').replaceWith(c),b.runTemplateJS(d)},i=function(a){b.render("tool_lp/plans_page",a).done(h).fail(d.exception)},j=function(){var a=c.call([{methodname:"tool_lp_delete_plan",args:{id:f}},{methodname:"tool_lp_data_for_plans_page",args:{userid:g}}]);a[1].done(i).fail(d.exception)},k=function(b){b.preventDefault();var g=a(this).attr("data-planid");f=g;var h=c.call([{methodname:"tool_lp_read_plan",args:{id:f}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"tool_lp"},{key:"deleteplan",component:"tool_lp",param:a.name},{key:"delete",component:"tool_lp"},{key:"cancel",component:"tool_lp"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],j)}).fail(d.exception)}).fail(d.exception)};return{init:function(){a('[data-region="plans"]').on("click",'[data-action="deleteplan"]',k),g=a('[data-region="plans"]').attr("data-userid")}}});
|
1
admin/tool/lp/amd/build/templatedelete.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/templatedelete.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=function(c,d){a('[data-region="managetemplates"]').replaceWith(c),b.runTemplateJS(d)},h=function(a){b.render("tool_lp/manage_templates_page",a).done(g).fail(d.exception)},i=function(){var a=c.call([{methodname:"tool_lp_delete_template",args:{id:f}},{methodname:"tool_lp_data_for_templates_manage_page",args:[]}]);a[1].done(h).fail(d.exception)},j=function(b){b.preventDefault();var g=a(this).attr("data-templateid");f=g;var h=c.call([{methodname:"tool_lp_read_template",args:{id:f}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"tool_lp"},{key:"deletetemplate",component:"tool_lp",param:a.shortname},{key:"delete",component:"tool_lp"},{key:"cancel",component:"tool_lp"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],i)}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:j}});
|
1
admin/tool/lp/amd/build/templatemove.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/templatemove.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["jquery","core/str","core/notification","core/ajax","tool_lp/dragdrop-reorder"],function(a,b,c,d,e){var f=function(b,e){var f=a(b).data("templateid"),g=a(e).data("templateid"),h=d.call([{methodname:"tool_lp_reorder_template",args:{from:f,to:g}}]);h[0].fail(c.exception)};return{init:function(){b.get_string("movetemplate","tool_lp").done(function(a){e.dragdrop("movetemplate",a,{identifier:"movetemplate",component:"tool_lp"},{identifier:"movetemplateafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",f)}).fail(c.exception)}}});
|
1
admin/tool/lp/amd/build/tree.min.js
vendored
Normal file
1
admin/tool/lp/amd/build/tree.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
define(["jquery","core/url"],function(a,b){var c=a('<img alt="" src="'+b.imageUrl("t/expanded")+'"/>'),d=a('<img alt="" src="'+b.imageUrl("t/collapsed")+'"/>'),e=function(b,c){this.treeRoot=a(b),this.items=this.treeRoot.find("li"),this.parents=this.treeRoot.find("li:has(ul)"),this.visibleItems=null,this.activeItem=null,this.selectCallback=c,this.keys={tab:9,enter:13,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,up:38,right:39,down:40,asterisk:106},this.init(),this.bindEventHandlers()};return e.prototype.init=function(){this.parents.attr("aria-expanded","true"),this.parents.prepend(c.clone()),this.items.attr("role","tree-item"),this.items.attr("tabindex","-1"),this.parents.attr("role","group"),this.treeRoot.attr("role","tree"),this.visibleItems=this.treeRoot.find("li")},e.prototype.expandGroup=function(a){var b=a.children("ul");b.show().attr("aria-hidden","false"),a.attr("aria-expanded","true"),a.children("img").attr("src",c.attr("src")),this.visibleItems=this.treeRoot.find("li:visible")},e.prototype.collapseGroup=function(a){var b=a.children("ul");b.hide().attr("aria-hidden","true"),a.attr("aria-expanded","false"),a.children("img").attr("src",d.attr("src")),this.visibleItems=this.treeRoot.find("li:visible")},e.prototype.toggleGroup=function(a){"true"==a.attr("aria-expanded")?this.collapseGroup(a):this.expandGroup(a)},e.prototype.updateFocus=function(a){this.items.attr("aria-selected","false").attr("tabindex","-1"),a.attr("aria-selected","true").attr("tabindex",0),this.selectCallback(a)},e.prototype.handleKeyDown=function(b,c){var d=this.visibleItems.index(b);if(c.altKey||c.ctrlKey||c.shiftKey&&c.keyCode!=this.keys.tab)return!0;switch(c.keyCode){case this.keys.home:return this.activeItem=this.parents.first(),this.activeItem.focus(),c.stopPropagation(),!1;case this.keys.end:return this.activeItem=this.visibleItems.last(),this.activeItem.focus(),c.stopPropagation(),!1;case this.keys.enter:case this.keys.space:return b.has("ul")&&this.toggleGroup(b,!0),c.stopPropagation(),!1;case this.keys.left:if(b.has("ul")&&"true"==b.attr("aria-expanded"))this.collapseGroup(b);else{var e=b.parent(),f=e.parent();this.activeItem=f,this.activeItem.focus()}return c.stopPropagation(),!1;case this.keys.right:return b.has("ul")&&"false"==b.attr("aria-expanded")?this.expandGroup(b):(this.activeItem=b.children("ul").children("li").first(),this.activeItem.focus()),c.stopPropagation(),!1;case this.keys.up:if(d>0){var g=this.visibleItems.eq(d-1);this.activeItem=g,g.focus()}return c.stopPropagation(),!1;case this.keys.down:if(d<this.visibleItems.length-1){var h=this.visibleItems.eq(d+1);this.activeItem=h,h.focus()}return c.stopPropagation(),!1;case this.keys.asterisk:var i=this;return this.parents.each(function(){i.expandGroup(a(this))}),c.stopPropagation(),!1}return!0},e.prototype.handleKeyPress=function(a,b){if(b.altKey||b.ctrlKey||b.shiftKey)return!0;switch(b.keyCode){case this.keys.tab:return!0;case this.keys.enter:case this.keys.home:case this.keys.end:case this.keys.left:case this.keys.right:case this.keys.up:case this.keys.down:return b.stopPropagation(),!1;default:var c=String.fromCharCode(b.which),d=!1,e=this.visibleItems.index(a),f=this.visibleItems.length,g=e+1;for(g==f&&(g=0);g!=e;){var h=this.visibleItems.eq(g),i=h.text().charAt(0);if(h.has("ul")&&(i=h.find("span").text().charAt(0)),i.toLowerCase()==c){d=!0;break}g+=1,g==f&&(g=0)}return d===!0&&(this.activeItem=this.visibleItems.eq(g),this.activeItem.focus()),b.stopPropagation(),!1}return!0},e.prototype.handleDblClick=function(a,b){return b.altKey||b.ctrlKey||b.shiftKey?!0:(this.activeItem=a,this.updateFocus(a),this.toggleGroup(a),b.stopPropagation(),!1)},e.prototype.handleClick=function(a,b){return b.altKey||b.ctrlKey||b.shiftKey?!0:(this.activeItem=a,this.updateFocus(a),b.stopPropagation(),!1)},e.prototype.handleBlur=function(){return!0},e.prototype.handleFocus=function(a){return null===this.activeItem&&(this.activeItem=a),this.updateFocus(this.activeItem),!0},e.prototype.bindEventHandlers=function(){var b=this;this.parents.dblclick(function(c){return b.handleDblClick(a(this),c)}),this.items.click(function(c){return b.handleClick(a(this),c)}),this.items.keydown(function(c){return b.handleKeyDown(a(this),c)}),this.items.keypress(function(c){return b.handleKeyPress(a(this),c)}),this.items.focus(function(c){return b.handleFocus(a(this),c)}),this.items.blur(function(c){return b.handleBlur(a(this),c)})},e});
|
|
@ -21,14 +21,21 @@
|
|||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dialogue', 'core/str', 'core/tree', 'core/dragdrop-reorder'],
|
||||
function($, notification, ajax, templates, dialogue, str, ariatree, dragdrop) {
|
||||
define(['jquery',
|
||||
'core/notification',
|
||||
'core/ajax',
|
||||
'core/templates',
|
||||
'tool_lp/dialogue',
|
||||
'core/str',
|
||||
'tool_lp/tree',
|
||||
'tool_lp/dragdrop-reorder'],
|
||||
function($, notification, ajax, templates, Dialogue, str, Ariatree, dragdrop) {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {int} itemid
|
||||
* @param {string} itemtype
|
||||
* @param {Number} itemid
|
||||
* @param {String} itemtype
|
||||
*/
|
||||
var competencies = function(itemid, itemtype) {
|
||||
this.itemid = itemid;
|
||||
|
@ -41,7 +48,7 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
|
||||
loadframeworks[0].done(function(frameworks) {
|
||||
localthis.frameworks = frameworks;
|
||||
if (frameworks.length == 0) {
|
||||
if (frameworks.length === 0) {
|
||||
templates.render('tool_lp/no_frameworks_warning', {})
|
||||
.done(function(html) {
|
||||
$('[data-region="actions"]').append(html);
|
||||
|
@ -55,6 +62,10 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
}).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the drag/drop code.
|
||||
* @method registerDragDrop
|
||||
*/
|
||||
competencies.prototype.registerDragDrop = function() {
|
||||
var localthis = this;
|
||||
// Init this module.
|
||||
|
@ -75,20 +86,32 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a drop from a drag/drop operation.
|
||||
*
|
||||
* @method handleDrop
|
||||
* @param {Node} drag The dragged node.
|
||||
* @param {Node} drop The dropped on node.
|
||||
*/
|
||||
competencies.prototype.handleDrop = function(drag, drop) {
|
||||
var fromid = $(drag).data('id');
|
||||
var toid = $(drop).data('id');
|
||||
var localthis = this;
|
||||
var requests = [];
|
||||
|
||||
if (localthis.itemtype == 'course') {
|
||||
var requests = ajax.call([
|
||||
{ methodname: 'tool_lp_reorder_course_competency',
|
||||
args: { courseid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid } }
|
||||
]);
|
||||
requests = ajax.call([
|
||||
{
|
||||
methodname: 'tool_lp_reorder_course_competency',
|
||||
args: { courseid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid }
|
||||
}
|
||||
]);
|
||||
} else if (localthis.itemtype == 'template') {
|
||||
var requests = ajax.call([
|
||||
{ methodname: 'tool_lp_reorder_template_competency',
|
||||
args: { templateid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid } }
|
||||
requests = ajax.call([
|
||||
{
|
||||
methodname: 'tool_lp_reorder_template_competency',
|
||||
args: { templateid: localthis.itemid, competencyidfrom: fromid, competencyidto: toid }
|
||||
}
|
||||
]);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -97,6 +120,12 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
requests[0].fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the search text from the input field and reload the tree based on the search.
|
||||
*
|
||||
* @method applyFilter
|
||||
* @param {Event} e The event that triggered the button.
|
||||
*/
|
||||
competencies.prototype.applyFilter = function(e) {
|
||||
e.preventDefault();
|
||||
var localthis = this;
|
||||
|
@ -118,18 +147,28 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
}
|
||||
}
|
||||
framework.selected = true;
|
||||
var context = { framework: framework, frameworks: localthis.frameworks, competencies: competencies, search: searchText };
|
||||
var context = {
|
||||
framework: framework,
|
||||
frameworks: localthis.frameworks,
|
||||
competencies: competencies,
|
||||
search: searchText
|
||||
};
|
||||
templates.render('tool_lp/link_course_competencies', context).done(function(html) {
|
||||
$('[data-region="competencylinktree"]').replaceWith(html);
|
||||
localthis.initLinkCourseCompetencies();
|
||||
}).fail(notification.exception);;
|
||||
}).fail(notification.exception);
|
||||
}).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* The link course competencies popup was just opened and we need to initialise it.
|
||||
*
|
||||
* @method initLinkCourseCompetencies
|
||||
*/
|
||||
competencies.prototype.initLinkCourseCompetencies = function() {
|
||||
var localthis = this;
|
||||
|
||||
var competencytree = new ariatree('[data-enhance=linktree]', function(target) {
|
||||
new Ariatree('[data-enhance=linktree]', function(target) {
|
||||
localthis.selectedCompetency = target.data('id');
|
||||
});
|
||||
|
||||
|
@ -148,6 +187,10 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
localthis.popup.close();
|
||||
});
|
||||
$('[data-region="competencylinktree"] [data-action="add"]').click(function(e) {
|
||||
var requests = [],
|
||||
pagerender = '',
|
||||
pageregion = '';
|
||||
|
||||
e.preventDefault();
|
||||
if (!localthis.selectedCompetency) {
|
||||
return;
|
||||
|
@ -157,23 +200,23 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
|
||||
// Add the link and reload the page template.
|
||||
if (localthis.itemtype == 'course') {
|
||||
var requests = ajax.call([
|
||||
requests = ajax.call([
|
||||
{ methodname: 'tool_lp_add_competency_to_course',
|
||||
args: { courseid: localthis.itemid, competencyid: localthis.selectedCompetency } },
|
||||
{ methodname: 'tool_lp_data_for_course_competencies_page',
|
||||
args: { courseid: localthis.itemid } }
|
||||
]);
|
||||
var pagerender = 'tool_lp/course_competencies_page';
|
||||
var pageregion = 'coursecompetenciespage';
|
||||
pagerender = 'tool_lp/course_competencies_page';
|
||||
pageregion = 'coursecompetenciespage';
|
||||
} else if (localthis.itemtype == 'template') {
|
||||
var requests = ajax.call([
|
||||
requests = ajax.call([
|
||||
{ methodname: 'tool_lp_add_competency_to_template',
|
||||
args: { templateid: localthis.itemid, competencyid: localthis.selectedCompetency } },
|
||||
{ methodname: 'tool_lp_data_for_template_competencies_page',
|
||||
args: { templateid: localthis.itemid } }
|
||||
]);
|
||||
var pagerender = 'tool_lp/template_competencies_page';
|
||||
var pageregion = 'templatecompetenciespage';
|
||||
pagerender = 'tool_lp/template_competencies_page';
|
||||
pageregion = 'templatecompetenciespage';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -188,35 +231,44 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Register the javascript event handlers for this page.
|
||||
*
|
||||
* @method registerEvents
|
||||
*/
|
||||
competencies.prototype.registerEvents = function() {
|
||||
var localthis = this;
|
||||
$('[data-region="actions"] button').click(function(e) {
|
||||
return localthis.openCompetencySelector.call(localthis, e);
|
||||
});
|
||||
$('[data-action="delete-competency-link"]').click(function(e) {
|
||||
var requests = [],
|
||||
pagerender = '',
|
||||
pageregion = '';
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var deleteid = $(e.target).closest('[data-id]').data('id');
|
||||
|
||||
// Delete the link and reload the page template.
|
||||
if (localthis.itemtype == 'course') {
|
||||
var requests = ajax.call([
|
||||
requests = ajax.call([
|
||||
{ methodname: 'tool_lp_remove_competency_from_course',
|
||||
args: { courseid: localthis.itemid, competencyid: deleteid } },
|
||||
{ methodname: 'tool_lp_data_for_course_competencies_page',
|
||||
args: { courseid: localthis.itemid } }
|
||||
]);
|
||||
var pagerender = 'tool_lp/course_competencies_page';
|
||||
var pageregion = 'coursecompetenciespage';
|
||||
pagerender = 'tool_lp/course_competencies_page';
|
||||
pageregion = 'coursecompetenciespage';
|
||||
} else if (localthis.itemtype == 'template') {
|
||||
var requests = ajax.call([
|
||||
requests = ajax.call([
|
||||
{ methodname: 'tool_lp_remove_competency_from_template',
|
||||
args: { templateid: localthis.itemid, competencyid: deleteid } },
|
||||
{ methodname: 'tool_lp_data_for_template_competencies_page',
|
||||
args: { templateid: localthis.itemid } }
|
||||
]);
|
||||
var pagerender = 'tool_lp/template_competencies_page';
|
||||
var pageregion = 'templatecompetenciespage';
|
||||
pagerender = 'tool_lp/template_competencies_page';
|
||||
pageregion = 'templatecompetenciespage';
|
||||
}
|
||||
|
||||
requests[1].done(function(context) {
|
||||
|
@ -228,6 +280,13 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn the flat list of competencies into a tree.
|
||||
*
|
||||
* @method addCompetencyChildren
|
||||
* @param {Object} parent The current parent node
|
||||
* @param {Object[]} competencies The flat list of all nodes.
|
||||
*/
|
||||
competencies.prototype.addCompetencyChildren = function(parent, competencies) {
|
||||
var i;
|
||||
|
||||
|
@ -242,6 +301,12 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the search text from the input, and reload the tree.
|
||||
*
|
||||
* @method searchCompetencies
|
||||
* @return {promise} When resolved it will contain the tree of competencies.
|
||||
*/
|
||||
competencies.prototype.searchCompetencies = function() {
|
||||
var localthis = this;
|
||||
var deferred = $.Deferred();
|
||||
|
@ -253,7 +318,7 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
var framework = $('[data-action="chooseframework"]');
|
||||
var frameworkid = localthis.frameworks[0].id;
|
||||
if (framework.length) {
|
||||
var frameworkid = framework.val();
|
||||
frameworkid = framework.val();
|
||||
}
|
||||
|
||||
var loadcompetencies = ajax.call([
|
||||
|
@ -265,7 +330,7 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
var i, competenciestree = [];
|
||||
for (i = 0; i < competencies.length; i++) {
|
||||
var onecompetency = competencies[i];
|
||||
if (onecompetency.parentid == 0) {
|
||||
if (onecompetency.parentid === "0") {
|
||||
onecompetency.children = [];
|
||||
onecompetency.haschildren = 0;
|
||||
competenciestree[competenciestree.length] = onecompetency;
|
||||
|
@ -278,6 +343,11 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
return deferred.promise();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a popup to choose competencies.
|
||||
*
|
||||
* @method openCompetencySelector
|
||||
*/
|
||||
competencies.prototype.openCompetencySelector = function(e) {
|
||||
e.preventDefault();
|
||||
var localthis = this;
|
||||
|
@ -287,16 +357,18 @@ define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dial
|
|||
framework.selected = true;
|
||||
var context = { framework: framework, frameworks: localthis.frameworks, competencies: competencies, search: '' };
|
||||
templates.render('tool_lp/link_course_competencies', context).done(function(html) {
|
||||
str.get_string('linkcompetencies', 'tool_lp').done(function(title) {;
|
||||
localthis.popup = new dialogue(
|
||||
str.get_string('linkcompetencies', 'tool_lp').done(function(title) {
|
||||
localthis.popup = new Dialogue(
|
||||
title,
|
||||
html, // The link UI.
|
||||
(function() {localthis.initLinkCourseCompetencies.call(localthis)})
|
||||
function() {
|
||||
localthis.initLinkCourseCompetencies.call(localthis);
|
||||
}
|
||||
);
|
||||
}).fail(notification.exception);
|
||||
}).fail(notification.exception);;
|
||||
}).fail(notification.exception);
|
||||
}).fail(notification.exception);
|
||||
};
|
||||
|
||||
return /** @alias module:core/tree */ competencies;
|
||||
return /** @alias module:tool_lp/coursecompetencies */ competencies;
|
||||
});
|
||||
|
|
|
@ -16,39 +16,55 @@
|
|||
/**
|
||||
* Handle selection changes and actions on the competency tree.
|
||||
*
|
||||
* @module tool_lp/competencyselect
|
||||
* @module tool_lp/competencyactions
|
||||
* @package tool_lp
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str', 'core/ajax', 'core/dragdrop-reorder', 'core/tree', 'core/dialogue', 'core/menu'],
|
||||
function($, url, templates, notification, str, ajax, dragdrop, ariatree, dialogue, menu) {
|
||||
define(['jquery',
|
||||
'core/url',
|
||||
'core/templates',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/ajax',
|
||||
'tool_lp/dragdrop-reorder',
|
||||
'tool_lp/tree',
|
||||
'tool_lp/dialogue',
|
||||
'tool_lp/menubar'],
|
||||
function($, url, templates, notification, str, ajax, dragdrop, Ariatree, Dialogue, menubar) {
|
||||
|
||||
// Private variables and functions.
|
||||
/** @var {Object} treeModel - This is an object representing the nodes in the tree. */
|
||||
var treeModel = null;
|
||||
|
||||
/** @var {Node} moveSource - The start of a drag operation */
|
||||
var moveSource = null;
|
||||
/** @var {Node} moveTarget - The end of a drag operation */
|
||||
var moveTarget = null;
|
||||
|
||||
var addHandler = function(e) {
|
||||
e.preventDefault();
|
||||
/**
|
||||
* Respond to choosing the "Add" menu item for the selected node in the tree.
|
||||
* @method addHandler
|
||||
*/
|
||||
var addHandler = function() {
|
||||
var parent = $('[data-region="competencyactions"]').data('competency');
|
||||
|
||||
var params = {
|
||||
competencyframeworkid : treeModel.getCompetencyFrameworkId()
|
||||
};
|
||||
|
||||
if (parent == null) {
|
||||
// We are adding at the root node.
|
||||
} else {
|
||||
if (parent !== null) {
|
||||
// We are adding at a sub node.
|
||||
params['parentid'] = parent.id;
|
||||
params.parentid = parent.id;
|
||||
}
|
||||
var queryparams = $.param(params);
|
||||
var actionurl = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams);
|
||||
window.location = actionurl;
|
||||
};
|
||||
|
||||
/**
|
||||
* A source and destination has been chosen - so time to complete a move.
|
||||
* @method doMove
|
||||
*/
|
||||
var doMove = function() {
|
||||
if (typeof (moveTarget) === "undefined") {
|
||||
// This is a top level node.
|
||||
|
@ -70,16 +86,27 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
requests[1].done(reloadPage).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* A move competency popup was opened - initialise the aria tree in it.
|
||||
* @method initMovePopup
|
||||
* @param {dialogue} The tool_lp/dialogue that was created.
|
||||
*/
|
||||
var initMovePopup = function(popup) {
|
||||
var movetree = new ariatree('[data-enhance=movetree]', function(target) {
|
||||
new Ariatree('[data-enhance=movetree]', function(target) {
|
||||
moveTarget = $(target).data('id');
|
||||
});
|
||||
|
||||
var body = $(popup.getContent());
|
||||
body.on('click', '[data-action="move"]', function(e) { popup.close(); doMove() });
|
||||
body.on('click', '[data-action="cancel"]', function(e) { popup.close(); });
|
||||
body.on('click', '[data-action="move"]', function() { popup.close(); doMove(); });
|
||||
body.on('click', '[data-action="cancel"]', function() { popup.close(); });
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn a flat list of competencies into a tree structure (recursive).
|
||||
* @method addCompetencyChildren
|
||||
* @param {Object} parent The current parent node in the tree
|
||||
* @param {Object[]} competencies The flat list of competencies
|
||||
*/
|
||||
var addCompetencyChildren = function(parent, competencies) {
|
||||
var i;
|
||||
|
||||
|
@ -94,8 +121,11 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
}
|
||||
};
|
||||
|
||||
var moveHandler = function(e) {
|
||||
e.preventDefault();
|
||||
/**
|
||||
* A node was chosen and "Move" was selected from the menu. Open a popup to select the target.
|
||||
* @method moveHandler
|
||||
*/
|
||||
var moveHandler = function() {
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
||||
// Remember what we are moving.
|
||||
|
@ -124,7 +154,7 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
var i, competenciestree = [];
|
||||
for (i = 0; i < competencies.length; i++) {
|
||||
var onecompetency = competencies[i];
|
||||
if (onecompetency.parentid == 0) {
|
||||
if (onecompetency.parentid === "0") {
|
||||
onecompetency.children = [];
|
||||
onecompetency.haschildren = 0;
|
||||
competenciestree[competenciestree.length] = onecompetency;
|
||||
|
@ -132,7 +162,7 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
}
|
||||
}
|
||||
|
||||
var strings = str.get_strings([
|
||||
str.get_strings([
|
||||
{ key: 'movecompetency', component: 'tool_lp', param: competency.shortname },
|
||||
{ key: 'move', component: 'tool_lp' },
|
||||
{ key: 'cancel', component: 'tool_lp' }
|
||||
|
@ -145,7 +175,7 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
|
||||
templates.render('tool_lp/competencies_move_tree', context)
|
||||
.done(function(tree) {
|
||||
var popup = new dialogue(
|
||||
new Dialogue(
|
||||
strings[0], // Move competency x.
|
||||
tree, // The move tree.
|
||||
initMovePopup
|
||||
|
@ -159,8 +189,11 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
|
||||
};
|
||||
|
||||
var editHandler = function(e) {
|
||||
e.preventDefault();
|
||||
/**
|
||||
* Edit the selected competency.
|
||||
* @method editHandler
|
||||
*/
|
||||
var editHandler = function() {
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
||||
var params = {
|
||||
|
@ -174,6 +207,10 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
window.location = actionurl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Re-render the page with the latest data.
|
||||
* @method reloadPage
|
||||
*/
|
||||
var reloadPage = function(context) {
|
||||
templates.render('tool_lp/manage_competencies_page', context)
|
||||
.done(function(newhtml, newjs) {
|
||||
|
@ -183,6 +220,10 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
.fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform a search and render the page with the new search results.
|
||||
* @method updateSearchHandler
|
||||
*/
|
||||
var updateSearchHandler = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -196,6 +237,10 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
requests[0].done(reloadPage).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a competency "up". This only affects the sort order within the same branch of the tree.
|
||||
* @method moveUpHandler
|
||||
*/
|
||||
var moveUpHandler = function() {
|
||||
// We are chaining ajax requests here.
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
@ -210,6 +255,10 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
requests[1].done(reloadPage).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a competency "down". This only affects the sort order within the same branch of the tree.
|
||||
* @method moveDownHandler
|
||||
*/
|
||||
var moveDownHandler = function() {
|
||||
// We are chaining ajax requests here.
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
@ -224,10 +273,12 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
requests[1].done(reloadPage).fail(notification.exception);
|
||||
};
|
||||
|
||||
var seeCoursesHandler = function(e) {
|
||||
e.preventDefault();
|
||||
/**
|
||||
* Open a dialogue to show all the courses using the selected competency.
|
||||
* @method seeCoursesHandler
|
||||
*/
|
||||
var seeCoursesHandler = function() {
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
var localthis = this;
|
||||
|
||||
var requests = ajax.call([{
|
||||
methodname: 'tool_lp_list_courses_using_competency',
|
||||
|
@ -241,7 +292,7 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
};
|
||||
templates.render('tool_lp/linked_courses_summary', context).done(function(html) {
|
||||
str.get_string('linkedcourses', 'tool_lp').done(function (linkedcourses) {
|
||||
var popup = new dialogue(
|
||||
new Dialogue(
|
||||
linkedcourses, // Title.
|
||||
html, // The linked courses.
|
||||
initMovePopup
|
||||
|
@ -249,8 +300,12 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
}).fail(notification.exception);
|
||||
}).fail(notification.exception);
|
||||
}).fail(notification.exception);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a competency.
|
||||
* @method doDelete
|
||||
*/
|
||||
var doDelete = function() {
|
||||
// We are chaining ajax requests here.
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
@ -265,14 +320,17 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
requests[1].done(reloadPage).fail(notification.exception);
|
||||
};
|
||||
|
||||
var deleteHandler = function(e) {
|
||||
e.preventDefault();
|
||||
/**
|
||||
* Show a confirm dialogue before deleting a competency.
|
||||
* @method deleteHandler
|
||||
*/
|
||||
var deleteHandler = function() {
|
||||
var competency = $('[data-region="competencyactions"]').data('competency');
|
||||
|
||||
templates.render('tool_lp/competency_summary', competency)
|
||||
.done(function(html) {
|
||||
|
||||
var strings = str.get_strings([
|
||||
str.get_strings([
|
||||
{ key: 'confirm', component: 'tool_lp' },
|
||||
{ key: 'deletecompetency', component: 'tool_lp', param: html },
|
||||
{ key: 'delete', component: 'tool_lp' },
|
||||
|
@ -290,25 +348,45 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
|
||||
* @method dragStart
|
||||
*/
|
||||
var dragStart = function(e) {
|
||||
e.originalEvent.dataTransfer.setData('text', $(e.target).data('id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
|
||||
* @method allowDrop
|
||||
*/
|
||||
var allowDrop = function(e) {
|
||||
e.originalEvent.dataTransfer.dropEffect = 'move';
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
|
||||
* @method dragEnter
|
||||
*/
|
||||
var dragEnter = function(e) {
|
||||
e.preventDefault();
|
||||
$(this).addClass('currentdragtarget');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
|
||||
* @method dragLeave
|
||||
*/
|
||||
var dragLeave = function(e) {
|
||||
e.preventDefault();
|
||||
$(this).removeClass('currentdragtarget');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML5 implementation of drag/drop (there is an accesible alternative in the menus).
|
||||
* @method dropOver
|
||||
*/
|
||||
var dropOver = function(e) {
|
||||
e.preventDefault();
|
||||
moveSource = e.originalEvent.dataTransfer.getData('text');
|
||||
|
@ -319,20 +397,27 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Initialise this page (attach event handlers etc).
|
||||
*
|
||||
* @method init
|
||||
* @param {Object} model The tree model provides some useful functions for loading and searching competencies.
|
||||
*/
|
||||
init: function(model) {
|
||||
treeModel = model;
|
||||
str.get_string('edit', 'core').done(function (edit) {
|
||||
menu.menu(edit, '.competencyactionsmenu');
|
||||
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="add"]', addHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="edit"]', editHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="delete"]', deleteHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="move"]', moveHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="moveup"]', moveUpHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="movedown"]', moveDownHandler);
|
||||
$('[data-region="competencyactions"]').on('click', '[data-action="linkedcourses"]', seeCoursesHandler);
|
||||
$('[data-region="competencyactions"]').on('click', addHandler);
|
||||
|
||||
menubar.enhance('.competencyactionsmenu', {
|
||||
'[data-action="edit"]': editHandler,
|
||||
'[data-action="delete"]': deleteHandler,
|
||||
'[data-action="move"]': moveHandler,
|
||||
'[data-action="moveup"]': moveUpHandler,
|
||||
'[data-action="movedown"]': moveDownHandler,
|
||||
'[data-action="linkedcourses"]': seeCoursesHandler
|
||||
});
|
||||
$('[data-region="competencyactionsmenu"]').hide();
|
||||
|
||||
}).fail(notification.exception);
|
||||
$('[data-region="filtercompetencies"]').on('submit', updateSearchHandler);
|
||||
// Simple html5 drag drop because we already added an accessible alternative.
|
||||
$('[data-region="managecompetencies"] li').on('dragstart', dragStart);
|
||||
|
@ -341,9 +426,14 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
$('[data-region="managecompetencies"] li').on('dragleave', dragLeave);
|
||||
$('[data-region="managecompetencies"] li').on('drop', dropOver);
|
||||
},
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Handler when a node in the aria tree is selected.
|
||||
* @method selectionChanged
|
||||
*/
|
||||
selectionChanged: function(node) {
|
||||
var id = $(node).data('id');
|
||||
menubar.closeAll();
|
||||
if (typeof id === "undefined") {
|
||||
// Assume this is the root of the tree.
|
||||
// Here we are only getting the text from the top of the tree, to do it we clone the tree,
|
||||
|
@ -355,6 +445,7 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
} else {
|
||||
var competency = treeModel.getCompetency(id);
|
||||
|
||||
$('[data-region="competencyactionsmenu"]').show();
|
||||
templates.render('tool_lp/competency_summary', competency)
|
||||
.done(function(html) {
|
||||
$('[data-region="competencyinfo"]').html(html);
|
||||
|
@ -362,7 +453,6 @@ define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str',
|
|||
|
||||
$('[data-region="competencyactions"]').data('competency', competency);
|
||||
$('[data-region="competencyactions"] [data-action="add"]').removeAttr("disabled");
|
||||
$('[data-region="competencyactionsmenu"]').css('display', 'inline-block');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,17 @@
|
|||
*/
|
||||
define(['core/ajax', 'core/notification', 'jquery'], function(ajax, notification, $) {
|
||||
// Private variables and functions.
|
||||
/** @var {Object[]} competencies - Cached list of competencies */
|
||||
var competencies = [];
|
||||
|
||||
/** @var {Number} competencyFrameworkId - The current framework id */
|
||||
var competencyFrameworkId = 0;
|
||||
|
||||
/**
|
||||
* Load the list of competencies via ajax. Competencies are filtered by the searchtext.
|
||||
* @param {String} searchtext The text to filter on.
|
||||
* @return {promise}
|
||||
*/
|
||||
var loadCompetencies = function(searchtext) {
|
||||
var deferred = $.Deferred();
|
||||
searchtext = '';
|
||||
|
@ -52,25 +59,52 @@
|
|||
};
|
||||
|
||||
|
||||
return {
|
||||
return /** @alias module:tool_lp/competencytree */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialise the tree.
|
||||
*
|
||||
* @param {Number} id The competency id.
|
||||
*/
|
||||
init: function(id) {
|
||||
competencyFrameworkId = id;
|
||||
loadCompetencies('').fail(notification.exception);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the competency framework id this model was initiliased with.
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
getCompetencyFrameworkId: function() {
|
||||
return competencyFrameworkId;
|
||||
},
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Get a competency by id
|
||||
*
|
||||
* @param {Number} id The competency id
|
||||
* @return {Object}
|
||||
*/
|
||||
getCompetency: function(id) {
|
||||
return competencies[id];
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all competencies for this framework.
|
||||
*
|
||||
* @return {Object[]}
|
||||
*/
|
||||
listCompetencies: function() {
|
||||
return competencies;
|
||||
},
|
||||
|
||||
/**
|
||||
* Reload the list of competencies, filtered by the search text.
|
||||
*
|
||||
* @param {String} searchtext The text to filter by.
|
||||
* @return {Object[]} The filtered competency list.
|
||||
*/
|
||||
applySearch: function(searchtext) {
|
||||
return loadCompetencies(searchtext);
|
||||
}
|
||||
|
|
76
admin/tool/lp/amd/src/dialogue.js
Normal file
76
admin/tool/lp/amd/src/dialogue.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Wrapper for the YUI M.core.notification class. Allows us to
|
||||
* use the YUI version in AMD code until it is replaced.
|
||||
*
|
||||
* @module tool_lp/dialogue
|
||||
* @package tool_lp
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/yui'], function(Y) {
|
||||
|
||||
// Private variables and functions.
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {String} title Title for the window.
|
||||
* @param {String} content The content for the window.
|
||||
* @param {function} afterShow Callback executed after the window is opened.
|
||||
*/
|
||||
var dialogue = function(title, content, afterShow) {
|
||||
this.yuiDialogue = null;
|
||||
var parent = this;
|
||||
|
||||
Y.use('moodle-core-notification', function () {
|
||||
|
||||
parent.yuiDialogue = new M.core.dialogue({
|
||||
headerContent: title,
|
||||
bodyContent: content,
|
||||
draggable: true,
|
||||
visible: false,
|
||||
center: true,
|
||||
modal: true
|
||||
});
|
||||
|
||||
parent.yuiDialogue.after('visibleChange', function(e) {
|
||||
if (e.newVal) {
|
||||
afterShow(parent);
|
||||
}
|
||||
});
|
||||
|
||||
parent.yuiDialogue.show();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Close this window.
|
||||
*/
|
||||
dialogue.prototype.close = function() {
|
||||
this.yuiDialogue.hide();
|
||||
this.yuiDialogue.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get content.
|
||||
*/
|
||||
dialogue.prototype.getContent = function() {
|
||||
return this.yuiDialogue.bodyNode.getDOMNode();
|
||||
};
|
||||
|
||||
return /** @alias module:tool_lp/dialogue */ dialogue;
|
||||
});
|
88
admin/tool/lp/amd/src/dragdrop-reorder.js
Normal file
88
admin/tool/lp/amd/src/dragdrop-reorder.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Drag and drop reorder via HTML5.
|
||||
*
|
||||
* @module tool_lp/dragdrop-reorder
|
||||
* @package tool_lp
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/str', 'core/yui'], function(str, Y) {
|
||||
|
||||
// Private variables and functions.
|
||||
|
||||
/**
|
||||
* Translate the drophit event from YUI
|
||||
* into simple drag and drop nodes.
|
||||
* @param {Y.Event} e The yui drop event.
|
||||
*/
|
||||
var proxyCallback = function(e) {
|
||||
var dragNode = e.drag.get('node');
|
||||
var dropNode = e.drop.get('node');
|
||||
this.callback(dragNode.getDOMNode(), dropNode.getDOMNode());
|
||||
};
|
||||
|
||||
return /** @alias module:tool_lp/dragdrop-reorder */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Create an instance of M.tool_lp.dragdrop
|
||||
*
|
||||
* @param {String} group Unique string to identify this interaction.
|
||||
* @param {String} dragHandleText Alt text for the drag handle.
|
||||
* @param {String} sameNodeText Used in keyboard drag drop for the list of items target.
|
||||
* @param {String} parentNodeText Used in keyboard drag drop for the parent target.
|
||||
* @param {String} sameNodeClass class used to find the each of the list of items.
|
||||
* @param {String} parentNodeClass class used to find the container for the list of items.
|
||||
* @param {String} dragHandleInsertClass class used to find the location to insert the drag handles.
|
||||
* @param {function} callback Drop hit handler.
|
||||
*/
|
||||
dragdrop: function(group,
|
||||
dragHandleText,
|
||||
sameNodeText,
|
||||
parentNodeText,
|
||||
sameNodeClass,
|
||||
parentNodeClass,
|
||||
dragHandleInsertClass,
|
||||
callback) {
|
||||
// Here we are wrapping YUI. This allows us to start transitioning, but
|
||||
// wait for a good alternative without having inconsistent UIs.
|
||||
str.get_strings([
|
||||
{ key: 'emptydragdropregion', component: 'moodle' },
|
||||
{ key: 'movecontent', component: 'moodle' },
|
||||
{ key: 'tocontent', component: 'moodle' },
|
||||
]).done( function () {
|
||||
Y.use('moodle-tool_lp-dragdrop-reorder', function () {
|
||||
|
||||
var context = {
|
||||
callback: callback
|
||||
};
|
||||
M.tool_lp.dragdrop_reorder({
|
||||
group: group,
|
||||
dragHandleText: dragHandleText,
|
||||
sameNodeText: sameNodeText,
|
||||
parentNodeText: parentNodeText,
|
||||
sameNodeClass: sameNodeClass,
|
||||
parentNodeClass: parentNodeClass,
|
||||
dragHandleInsertClass: dragHandleInsertClass,
|
||||
callback: Y.bind(proxyCallback, context)
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
});
|
|
@ -30,8 +30,8 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
/**
|
||||
* Callback to replace the dom element with the rendered template.
|
||||
*
|
||||
* @param {string} newhtml The new html to insert.
|
||||
* @param {string} newjs The new js to run.
|
||||
* @param {String} newhtml The new html to insert.
|
||||
* @param {String} newjs The new js to run.
|
||||
*/
|
||||
var updatePage = function(newhtml, newjs) {
|
||||
$('[data-region="managecompetencies"]').replaceWith(newhtml);
|
||||
|
@ -81,7 +81,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
}]);
|
||||
|
||||
requests[0].done(function(framework) {
|
||||
var strings = str.get_strings([
|
||||
str.get_strings([
|
||||
{ key: 'confirm', component: 'tool_lp' },
|
||||
{ key: 'deletecompetencyframework', component: 'tool_lp', param: framework.shortname },
|
||||
{ key: 'delete', component: 'tool_lp' },
|
||||
|
@ -100,19 +100,14 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
};
|
||||
|
||||
|
||||
return {
|
||||
return /** @alias module:tool_lp/frameworkdelete */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialise this plugin. Just attaches some event handlers to the delete entries in the menu.
|
||||
*/
|
||||
init: function() {
|
||||
// Init this module.
|
||||
$('[data-region="managecompetencies"]').on(
|
||||
"click",
|
||||
'[data-action="deletecompetencyframework"]',
|
||||
confirmDelete
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the event handler for delete.
|
||||
* @method deleteHandler
|
||||
* @param {Event} e
|
||||
*/
|
||||
deleteHandler: confirmDelete
|
||||
};
|
||||
});
|
||||
|
|
|
@ -16,22 +16,23 @@
|
|||
/**
|
||||
* Move competency frameworks via ajax.
|
||||
*
|
||||
* @module tool_lp/frameworkdelete
|
||||
* @module tool_lp/frameworkmove
|
||||
* @package tool_lp
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/dragdrop-reorder',
|
||||
define(['jquery',
|
||||
'core/str',
|
||||
'core/notification',
|
||||
'jquery',
|
||||
'core/ajax'],
|
||||
function(dragdrop, str, notification, $, ajax) {
|
||||
'core/ajax',
|
||||
'tool_lp/dragdrop-reorder'],
|
||||
function($, str, notification, ajax, dragdrop) {
|
||||
// Private variables and functions.
|
||||
|
||||
/**
|
||||
* Handle a drop on a node.
|
||||
*
|
||||
* @method handleDrop
|
||||
* @param {DOMNode} drag
|
||||
* @param {DOMNode} drop
|
||||
*/
|
||||
|
@ -47,10 +48,11 @@ define(['core/dragdrop-reorder',
|
|||
|
||||
};
|
||||
|
||||
return {
|
||||
return /** @alias module:tool_lp/frameworkmove */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialise this plugin. It loads some strings, then adds the drag/drop functions.
|
||||
* @method init
|
||||
*/
|
||||
init: function() {
|
||||
// Init this module.
|
||||
|
|
831
admin/tool/lp/amd/src/menubar.js
Normal file
831
admin/tool/lp/amd/src/menubar.js
Normal file
|
@ -0,0 +1,831 @@
|
|||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Aria menubar functionality. Enhances a simple nested list structure into a full aria widget.
|
||||
* Based on the open ajax example: http://oaa-accessibility.org/example/26/
|
||||
*
|
||||
* @module tool_lp/menubar
|
||||
* @package tool_lp
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery'], function($) {
|
||||
|
||||
/**
|
||||
* Close all open submenus anywhere in the page (there should only ever be one open at a time).
|
||||
*
|
||||
* @method closeAllSubMenus
|
||||
*/
|
||||
var closeAllSubMenus = function() {
|
||||
$('.tool-lp-menu .tool-lp-sub-menu').attr('aria-hidden', 'true');
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {$} Jquery collection matching the root of the menu.
|
||||
* @param {Function[]} handlers, called when a menu item is chosen.
|
||||
*/
|
||||
var Menubar = function(menuRoot, handlers) {
|
||||
// Setup private class variables.
|
||||
this.menuRoot = menuRoot;
|
||||
this.handlers = handlers;
|
||||
this.rootMenus = this.menuRoot.children('li');
|
||||
this.subMenus = this.rootMenus.children('ul');
|
||||
this.subMenuItems = this.subMenus.children('li');
|
||||
this.allItems = this.rootMenus.add(this.subMenuItems);
|
||||
this.activeItem = null;
|
||||
this.isChildOpen = false;
|
||||
|
||||
this.keys = {
|
||||
tab: 9,
|
||||
enter: 13,
|
||||
esc: 27,
|
||||
space: 32,
|
||||
left: 37,
|
||||
up: 38,
|
||||
right: 39,
|
||||
down: 40
|
||||
};
|
||||
|
||||
this.addAriaAttributes();
|
||||
// Add the event listeners.
|
||||
this.addEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a submenu, first it closes all other sub-menus and sets the open direction.
|
||||
* @method openSubMenu
|
||||
* @param {Node} menu
|
||||
*/
|
||||
Menubar.prototype.openSubMenu = function(menu) {
|
||||
this.setOpenDirection();
|
||||
closeAllSubMenus();
|
||||
menu.attr('aria-hidden', 'false');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Bind the event listeners to the DOM
|
||||
* @method addEventListeners
|
||||
*/
|
||||
Menubar.prototype.addEventListeners = function() {
|
||||
var currentThis = this;
|
||||
|
||||
// Hovers.
|
||||
this.subMenuItems.mouseenter(function() {
|
||||
$(this).addClass('menu-hover');
|
||||
return true;
|
||||
});
|
||||
|
||||
this.subMenuItems.mouseout(function() {
|
||||
$(this).removeClass('menu-hover');
|
||||
return true;
|
||||
});
|
||||
|
||||
// Mouse listeners.
|
||||
this.allItems.click(function(e) {
|
||||
return currentThis.handleClick($(this), e);
|
||||
});
|
||||
|
||||
// Key listeners.
|
||||
this.allItems.keydown(function(e) {
|
||||
return currentThis.handleKeyDown($(this), e);
|
||||
});
|
||||
|
||||
this.allItems.focus(function() {
|
||||
return currentThis.handleFocus($(this));
|
||||
});
|
||||
|
||||
this.allItems.blur(function() {
|
||||
return currentThis.handleBlur($(this));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Process click events for the top menus.
|
||||
*
|
||||
* @method handleClick
|
||||
* @param {Object} item is the jquery object of the item firing the event
|
||||
* @param {Event} e is the associated event object
|
||||
* @return boolean Returns false
|
||||
*/
|
||||
Menubar.prototype.handleClick = function(item, e) {
|
||||
var parentUL = item.parent();
|
||||
|
||||
if (parentUL.is('.tool-lp-menu')) {
|
||||
// Toggle the child menu open/closed.
|
||||
if (item.children('ul').first().attr('aria-hidden') == 'true') {
|
||||
this.openSubMenu(item.children('ul').first());
|
||||
} else {
|
||||
item.children('ul').first().attr('aria-hidden', 'true');
|
||||
}
|
||||
e.stopPropagation();
|
||||
} else {
|
||||
// Remove hover and focus styling.
|
||||
this.allItems.removeClass('menu-hover menu-focus');
|
||||
|
||||
// Close the menu.
|
||||
this.menuRoot.find('ul').not('.root-level').attr('aria-hidden','true');
|
||||
// Follow any link, or call the click handlers.
|
||||
var anchor = item.find('a').first();
|
||||
var clickEvent = new $.Event('click');
|
||||
clickEvent.target = anchor;
|
||||
var eventHandled = false;
|
||||
if (this.handlers) {
|
||||
$.each(this.handlers, function(selector, handler) {
|
||||
if (eventHandled) {
|
||||
return false;
|
||||
}
|
||||
if (item.find(selector).length > 0) {
|
||||
var callable = $.proxy(handler, anchor);
|
||||
// False means stop propogatting events.
|
||||
eventHandled = (callable(clickEvent) === false) || clickEvent.isDefaultPrevented();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!eventHandled) {
|
||||
window.location.href = anchor.attr('href');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
* Process focus events for the menu.
|
||||
*
|
||||
* @method handleFocus
|
||||
* @param {Object} item is the jquery object of the item firing the event
|
||||
* @return boolean Returns false
|
||||
*/
|
||||
Menubar.prototype.handleFocus = function(item) {
|
||||
|
||||
// If activeItem is null, we are getting focus from outside the menu. Store
|
||||
// the item that triggered the event.
|
||||
if (this.activeItem === null) {
|
||||
this.activeItem = item;
|
||||
} else if (item[0] != this.activeItem[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the set of jquery objects for all the parent items of the active item.
|
||||
var parentItems = this.activeItem.parentsUntil('ul.tool-lp-menu').filter('li');
|
||||
|
||||
// Remove focus styling from all other menu items.
|
||||
this.allItems.removeClass('menu-focus');
|
||||
|
||||
// Add focus styling to the active item.
|
||||
this.activeItem.addClass('menu-focus');
|
||||
|
||||
// Add focus styling to all parent items.
|
||||
parentItems.addClass('menu-focus');
|
||||
|
||||
// If the bChildOpen flag has been set, open the active item's child menu (if applicable).
|
||||
if (this.isChildOpen === true) {
|
||||
|
||||
var itemUL = item.parent();
|
||||
|
||||
// If the itemUL is a root-level menu and item is a parent item,
|
||||
// show the child menu.
|
||||
if (itemUL.is('.tool-lp-menu') && (item.attr('aria-haspopup') == 'true')) {
|
||||
this.openSubMenu(item.children('ul').first());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
* Process blur events for the menu.
|
||||
*
|
||||
* @method handleBlur
|
||||
* @param {Object} item is the jquery object of the item firing the event
|
||||
* @return boolean Returns false
|
||||
*/
|
||||
Menubar.prototype.handleBlur = function(item) {
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine if the menu should open to the left, or the right,
|
||||
* based on the screen size and menu position.
|
||||
* @method setOpenDirection
|
||||
*/
|
||||
Menubar.prototype.setOpenDirection = function() {
|
||||
var pos = this.menuRoot.offset();
|
||||
var isRTL = $(document.body).hasClass('dir-rtl');
|
||||
var menuMinWidth = 160;
|
||||
var openLeft = false;
|
||||
|
||||
if (isRTL) {
|
||||
if (pos.left - menuMinWidth < 0) {
|
||||
openLeft = true;
|
||||
}
|
||||
} else {
|
||||
if (pos.left + menuMinWidth > $( window ).width()) {
|
||||
openLeft = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (openLeft) {
|
||||
this.menuRoot.addClass('tool-lp-menu-open-left');
|
||||
} else {
|
||||
this.menuRoot.removeClass('tool-lp-menu-open-left');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Process keyDown events for the menu.
|
||||
*
|
||||
* @method handleKeyDown
|
||||
* @param {Object} item is the jquery object of the item firing the event
|
||||
* @param {Event} e is the associated event object
|
||||
* @return boolean Returns false if consuming the event
|
||||
*/
|
||||
Menubar.prototype.handleKeyDown = function(item, e) {
|
||||
|
||||
if (e.altKey || e.ctrlKey) {
|
||||
// Modifier key pressed: Do not process.
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(e.keyCode) {
|
||||
case this.keys.tab: {
|
||||
|
||||
// Hide all menu items and update their aria attributes.
|
||||
this.menuRoot.find('ul').attr('aria-hidden', 'true');
|
||||
|
||||
// Remove focus styling from all menu items.
|
||||
this.allItems.removeClass('menu-focus');
|
||||
|
||||
this.activeItem = null;
|
||||
|
||||
this.isChildOpen = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case this.keys.esc: {
|
||||
var itemUL = item.parent();
|
||||
|
||||
if (itemUL.is('.tool-lp-menu')) {
|
||||
// Hide the child menu and update the aria attributes.
|
||||
item.children('ul').first().attr('aria-hidden', 'true');
|
||||
} else {
|
||||
|
||||
// Move up one level.
|
||||
this.activeItem = itemUL.parent();
|
||||
|
||||
// Reset the isChildOpen flag.
|
||||
this.isChildOpen = false;
|
||||
|
||||
// Set focus on the new item.
|
||||
this.activeItem.focus();
|
||||
|
||||
// Hide the active menu and update the aria attributes.
|
||||
itemUL.attr('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.enter:
|
||||
case this.keys.space: {
|
||||
|
||||
var parentUL = item.parent();
|
||||
|
||||
if (parentUL.is('.tool-lp-menu')) {
|
||||
// Open the child menu if it is closed.
|
||||
this.openSubMenu(item.children('ul').first());
|
||||
} else {
|
||||
|
||||
// Remove hover and focus styling.
|
||||
this.allItems.removeClass('menu-hover');
|
||||
this.allItems.removeClass('menu-focus');
|
||||
|
||||
// Close the menu.
|
||||
this.menuRoot.find('ul').not('.tool-lp-menu').attr('aria-hidden','true');
|
||||
|
||||
|
||||
// Clear the active item.
|
||||
this.activeItem = null;
|
||||
// Call the handler.
|
||||
// Follow any link, or call the click handlers.
|
||||
var anchor = item.find('a').first();
|
||||
var clickEvent = new $.Event('click');
|
||||
clickEvent.target = anchor;
|
||||
var eventHandled = false;
|
||||
if (this.handlers) {
|
||||
$.each(this.handlers, function(selector, handler) {
|
||||
if (eventHandled) {
|
||||
return false;
|
||||
}
|
||||
if (item.find(selector).length > 0) {
|
||||
var callable = $.proxy(handler, anchor);
|
||||
// False means stop propogatting events.
|
||||
eventHandled = (callable(clickEvent) === false) || clickEvent.isDefaultPrevented();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!eventHandled) {
|
||||
window.location.href = anchor.attr('href');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
case this.keys.left: {
|
||||
|
||||
this.activeItem = this.moveToPrevious(item);
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.right: {
|
||||
|
||||
this.activeItem = this.moveToNext(item);
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.up: {
|
||||
|
||||
this.activeItem = this.moveUp(item);
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.down: {
|
||||
|
||||
this.activeItem = this.moveDown(item);
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Move to the next menu level.
|
||||
* This will be either the next root-level menu or the child of a menu parent. If
|
||||
* at the root level and the active item is the last in the menu, this function will loop
|
||||
* to the first menu item.
|
||||
*
|
||||
* If the menu is a horizontal menu, the first child element of the newly selected menu will
|
||||
* be selected
|
||||
*
|
||||
* @method moveToNext
|
||||
* @param {Object} item is the active menu item
|
||||
* @return {Object} Returns the item to move to. Returns item is no move is possible
|
||||
*/
|
||||
Menubar.prototype.moveToNext = function(item) {
|
||||
// Item's containing menu.
|
||||
var itemUL = item.parent();
|
||||
|
||||
// The items in the currently active menu.
|
||||
var menuItems = itemUL.children('li');
|
||||
|
||||
// The number of items in the active menu.
|
||||
var menuNum = menuItems.length;
|
||||
// The items index in its menu.
|
||||
var menuIndex = menuItems.index(item);
|
||||
var newItem = null;
|
||||
var childMenu = null;
|
||||
|
||||
if (itemUL.is('.tool-lp-menu')) {
|
||||
// This is the root level move to next sibling. This will require closing
|
||||
// the current child menu and opening the new one.
|
||||
|
||||
if (menuIndex < menuNum-1) {
|
||||
// Not the last root menu.
|
||||
newItem = item.next();
|
||||
} else { // Wrap to first item.
|
||||
newItem = menuItems.first();
|
||||
}
|
||||
|
||||
// Close the current child menu (if applicable).
|
||||
if (item.attr('aria-haspopup') == 'true') {
|
||||
|
||||
childMenu = item.children('ul').first();
|
||||
|
||||
if (childMenu.attr('aria-hidden') == 'false') {
|
||||
// Update the child menu's aria-hidden attribute.
|
||||
childMenu.attr('aria-hidden', 'true');
|
||||
this.isChildOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the focus styling from the current menu.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
// Open the new child menu (if applicable).
|
||||
if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {
|
||||
|
||||
childMenu = newItem.children('ul').first();
|
||||
|
||||
// Update the child's aria-hidden attribute.
|
||||
this.openSubMenu(childMenu);
|
||||
}
|
||||
} else {
|
||||
// This is not the root level. If there is a child menu to be moved into, do that;
|
||||
// otherwise, move to the next root-level menu if there is one.
|
||||
if (item.attr('aria-haspopup') == 'true') {
|
||||
|
||||
childMenu = item.children('ul').first();
|
||||
|
||||
newItem = childMenu.children('li').first();
|
||||
|
||||
// Show the child menu and update its aria attributes.
|
||||
this.openSubMenu(childMenu);
|
||||
} else {
|
||||
// At deepest level, move to the next root-level menu.
|
||||
|
||||
var parentMenus = null;
|
||||
var rootItem = null;
|
||||
|
||||
// Get list of all parent menus for item, up to the root level.
|
||||
parentMenus = item.parentsUntil('ul.tool-lp-menu').filter('ul').not('.tool-lp-menu');
|
||||
|
||||
// Hide the current menu and update its aria attributes accordingly.
|
||||
parentMenus.attr('aria-hidden', 'true');
|
||||
|
||||
// Remove the focus styling from the active menu.
|
||||
parentMenus.find('li').removeClass('menu-focus');
|
||||
parentMenus.last().parent().removeClass('menu-focus');
|
||||
|
||||
// The containing root for the menu.
|
||||
rootItem = parentMenus.last().parent();
|
||||
|
||||
menuIndex = this.rootMenus.index(rootItem);
|
||||
|
||||
// If this is not the last root menu item, move to the next one.
|
||||
if (menuIndex < this.rootMenus.length-1) {
|
||||
newItem = rootItem.next();
|
||||
} else {
|
||||
// Loop.
|
||||
newItem = this.rootMenus.first();
|
||||
}
|
||||
|
||||
// Add the focus styling to the new menu.
|
||||
newItem.addClass('menu-focus');
|
||||
|
||||
if (newItem.attr('aria-haspopup') == 'true') {
|
||||
childMenu = newItem.children('ul').first();
|
||||
|
||||
newItem = childMenu.children('li').first();
|
||||
|
||||
// Show the child menu and update it's aria attributes.
|
||||
this.openSubMenu(childMenu);
|
||||
this.isChildOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newItem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Member function to move to the previous menu level.
|
||||
* This will be either the previous root-level menu or the child of a menu parent. If
|
||||
* at the root level and the active item is the first in the menu, this function will loop
|
||||
* to the last menu item.
|
||||
*
|
||||
* If the menu is a horizontal menu, the first child element of the newly selected menu will
|
||||
* be selected
|
||||
*
|
||||
* @method moveToPrevious
|
||||
* @param {Object} item is the active menu item
|
||||
* @return {Object} Returns the item to move to. Returns item is no move is possible
|
||||
*/
|
||||
Menubar.prototype.moveToPrevious = function(item) {
|
||||
// Item's containing menu.
|
||||
var itemUL = item.parent();
|
||||
// The items in the currently active menu.
|
||||
var menuItems = itemUL.children('li');
|
||||
// The items index in its menu.
|
||||
var menuIndex = menuItems.index(item);
|
||||
var newItem = null;
|
||||
var childMenu = null;
|
||||
|
||||
if (itemUL.is('.tool-lp-menu')) {
|
||||
// This is the root level move to previous sibling. This will require closing
|
||||
// the current child menu and opening the new one.
|
||||
|
||||
if (menuIndex > 0) {
|
||||
// Not the first root menu.
|
||||
newItem = item.prev();
|
||||
} else {
|
||||
// Wrap to last item.
|
||||
newItem = menuItems.last();
|
||||
}
|
||||
|
||||
// Close the current child menu (if applicable).
|
||||
if (item.attr('aria-haspopup') == 'true') {
|
||||
childMenu = item.children('ul').first();
|
||||
|
||||
if (childMenu.attr('aria-hidden') == 'false') {
|
||||
// Update the child menu's aria-hidden attribute.
|
||||
childMenu.attr('aria-hidden', 'true');
|
||||
this.isChildOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the focus styling from the current menu.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
// Open the new child menu (if applicable).
|
||||
if ((newItem.attr('aria-haspopup') === 'true') && (this.isChildOpen === true)) {
|
||||
|
||||
childMenu = newItem.children('ul').first();
|
||||
|
||||
// Update the child's aria-hidden attribute.
|
||||
this.openSubMenu(childMenu);
|
||||
|
||||
}
|
||||
} else {
|
||||
// This is not the root level. If there is a parent menu that is not the
|
||||
// root menu, move up one level; otherwise, move to first item of the previous
|
||||
// root menu.
|
||||
|
||||
var parentLI = itemUL.parent();
|
||||
var parentUL = parentLI.parent();
|
||||
|
||||
// If this is a vertical menu or is not the first child menu
|
||||
// of the root-level menu, move up one level.
|
||||
if (!parentUL.is('.tool-lp-menu')) {
|
||||
|
||||
newItem = itemUL.parent();
|
||||
|
||||
// Hide the active menu and update aria-hidden.
|
||||
itemUL.attr('aria-hidden', 'true');
|
||||
|
||||
// Remove the focus highlight from the item.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
} else {
|
||||
// Move to previous root-level menu.
|
||||
|
||||
// Hide the current menu and update the aria attributes accordingly.
|
||||
itemUL.attr('aria-hidden', 'true');
|
||||
|
||||
// Remove the focus styling from the active menu.
|
||||
item.removeClass('menu-focus');
|
||||
parentLI.removeClass('menu-focus');
|
||||
|
||||
menuIndex = this.rootMenus.index(parentLI);
|
||||
|
||||
if (menuIndex > 0) {
|
||||
// Move to the previous root-level menu.
|
||||
newItem = parentLI.prev();
|
||||
} else {
|
||||
// Loop to last root-level menu.
|
||||
newItem = this.rootMenus.last();
|
||||
}
|
||||
|
||||
// Add the focus styling to the new menu.
|
||||
newItem.addClass('menu-focus');
|
||||
|
||||
if (newItem.attr('aria-haspopup') == 'true') {
|
||||
childMenu = newItem.children('ul').first();
|
||||
|
||||
// Show the child menu and update it's aria attributes.
|
||||
this.openSubMenu(childMenu);
|
||||
this.isChildOpen = true;
|
||||
|
||||
newItem = childMenu.children('li').first();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newItem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Member function to select the next item in a menu.
|
||||
* If the active item is the last in the menu, this function will loop to the
|
||||
* first menu item.
|
||||
*
|
||||
* @method moveDown
|
||||
* @param {Object} item is the active menu item
|
||||
* @param {String} startChr is the character to attempt to match against the beginning of the
|
||||
* menu item titles. If found, focus moves to the next menu item beginning with that character.
|
||||
* @return {Object} Returns the item to move to. Returns item is no move is possible
|
||||
*/
|
||||
Menubar.prototype.moveDown = function(item, startChr) {
|
||||
// Item's containing menu.
|
||||
var itemUL = item.parent();
|
||||
// The items in the currently active menu.
|
||||
var menuItems = itemUL.children('li').not('.separator');
|
||||
// The number of items in the active menu.
|
||||
var menuNum = menuItems.length;
|
||||
// The items index in its menu.
|
||||
var menuIndex = menuItems.index(item);
|
||||
var newItem = null;
|
||||
var newItemUL = null;
|
||||
|
||||
if (itemUL.is('.tool-lp-menu')) {
|
||||
// This is the root level menu.
|
||||
|
||||
if (item.attr('aria-haspopup') != 'true') {
|
||||
// No child menu to move to.
|
||||
return item;
|
||||
}
|
||||
|
||||
// Move to the first item in the child menu.
|
||||
newItemUL = item.children('ul').first();
|
||||
newItem = newItemUL.children('li').first();
|
||||
|
||||
// Make sure the child menu is visible.
|
||||
this.openSubMenu(newItemUL);
|
||||
|
||||
return newItem;
|
||||
}
|
||||
|
||||
// If $item is not the last item in its menu, move to the next item. If startChr is specified, move
|
||||
// to the next item with a title that begins with that character.
|
||||
if (startChr) {
|
||||
var match = false;
|
||||
var curNdx = menuIndex+1;
|
||||
|
||||
// Check if the active item was the last one on the list.
|
||||
if (curNdx == menuNum) {
|
||||
curNdx = 0;
|
||||
}
|
||||
|
||||
// Iterate through the menu items (starting from the current item and wrapping) until a match is found
|
||||
// or the loop returns to the current menu item.
|
||||
while (curNdx != menuIndex) {
|
||||
|
||||
var titleChr = menuItems.eq(curNdx).html().charAt(0);
|
||||
|
||||
if (titleChr.toLowerCase() == startChr) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
curNdx = curNdx+1;
|
||||
|
||||
if (curNdx == menuNum) {
|
||||
// Reached the end of the list, start again at the beginning.
|
||||
curNdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (match === true) {
|
||||
newItem = menuItems.eq(curNdx);
|
||||
|
||||
// Remove the focus styling from the current item.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
return newItem;
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
} else {
|
||||
if (menuIndex < menuNum-1) {
|
||||
newItem = menuItems.eq(menuIndex+1);
|
||||
} else {
|
||||
newItem = menuItems.first();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the focus styling from the current item.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
return newItem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function moveUp() is a member function to select the previous item in a menu.
|
||||
* If the active item is the first in the menu, this function will loop to the
|
||||
* last menu item.
|
||||
*
|
||||
* @method moveUp
|
||||
* @param {Object} item is the active menu item
|
||||
* @return {Object} Returns the item to move to. Returns item is no move is possible
|
||||
*/
|
||||
Menubar.prototype.moveUp = function(item) {
|
||||
// Item's containing menu.
|
||||
var itemUL = item.parent();
|
||||
// The items in the currently active menu.
|
||||
var menuItems = itemUL.children('li').not('.separator');
|
||||
// The items index in its menu.
|
||||
var menuIndex = menuItems.index(item);
|
||||
var newItem = null;
|
||||
|
||||
if (itemUL.is('.tool-lp-menu')) {
|
||||
// This is the root level menu.
|
||||
// Nothing to do.
|
||||
return item;
|
||||
}
|
||||
|
||||
// If item is not the first item in its menu, move to the previous item.
|
||||
if (menuIndex > 0) {
|
||||
newItem = menuItems.eq(menuIndex-1);
|
||||
} else {
|
||||
// Loop to top of menu.
|
||||
newItem = menuItems.last();
|
||||
}
|
||||
|
||||
// Remove the focus styling from the current item.
|
||||
item.removeClass('menu-focus');
|
||||
|
||||
return newItem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enhance the dom with aria attributes.
|
||||
* @method addAriaAttributes
|
||||
*/
|
||||
Menubar.prototype.addAriaAttributes = function() {
|
||||
this.menuRoot.attr('role', 'menubar');
|
||||
this.rootMenus.attr('role', 'menuitem');
|
||||
this.rootMenus.attr('tabindex', '0');
|
||||
this.rootMenus.attr('aria-haspopup', 'true');
|
||||
this.subMenus.attr('role', 'menu');
|
||||
this.subMenus.attr('aria-hidden', 'true');
|
||||
this.subMenuItems.attr('role', 'menuitem');
|
||||
this.subMenuItems.attr('tabindex', '-1');
|
||||
|
||||
// For CSS styling and effects.
|
||||
this.menuRoot.addClass('tool-lp-menu');
|
||||
this.allItems.addClass('tool-lp-menu-item');
|
||||
this.rootMenus.addClass('tool-lp-root-menu');
|
||||
this.subMenus.addClass('tool-lp-sub-menu');
|
||||
};
|
||||
|
||||
return /** @alias module:tool_lp/menubar */ {
|
||||
/**
|
||||
* Create a menu bar object for every node matching the selector.
|
||||
*
|
||||
* The expected DOM structure is shown below.
|
||||
* <ul> <- This is the target of the selector parameter.
|
||||
* <li> <- This is repeated for each top level menu.
|
||||
* Text <- This is the text for the top level menu.
|
||||
* <ul> <- This is a list of the entries in this top level menu.
|
||||
* <li> <- This is repeated for each menu entry.
|
||||
* <a href="someurl">Choice 1</a> <- The anchor for the menu.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @method enhance
|
||||
* @param {String} selector - The selector for the outer most menu node.
|
||||
* @param {Function} handler - Javascript handler for when a menu item was chosen. If the
|
||||
* handler returns true (or does not exist), the
|
||||
* menu will look for an anchor with a link to follow.
|
||||
* For example, if the menu entry has a "data-action" attribute
|
||||
* and we want to call a javascript function when that entry is chosen,
|
||||
* we could pass a list of handlers like this:
|
||||
* { "[data-action='add']" : callAddFunction }
|
||||
*/
|
||||
enhance: function(selector, handler) {
|
||||
$(selector).each(function (index, element) {
|
||||
var menuRoot = $(element);
|
||||
// Don't enhance the same menu twice.
|
||||
if (menuRoot.data("menubarEnhanced") !== true) {
|
||||
(new Menubar(menuRoot, handler));
|
||||
menuRoot.data("menubarEnhanced", true);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handy function to close all open menus anywhere on the page.
|
||||
* @method closeAll
|
||||
*/
|
||||
closeAll: closeAllSubMenus
|
||||
};
|
||||
});
|
|
@ -84,7 +84,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
}]);
|
||||
|
||||
requests[0].done(function(plan) {
|
||||
var strings = str.get_strings([
|
||||
str.get_strings([
|
||||
{ key: 'confirm', component: 'tool_lp' },
|
||||
{ key: 'deleteplan', component: 'tool_lp', param: plan.name },
|
||||
{ key: 'delete', component: 'tool_lp' },
|
||||
|
|
|
@ -30,8 +30,9 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
/**
|
||||
* Callback to replace the dom element with the rendered template.
|
||||
*
|
||||
* @param {string} newhtml The new html to insert.
|
||||
* @param {string} newjs The new js to run.
|
||||
* @method updatePage
|
||||
* @param {String} newhtml The new html to insert.
|
||||
* @param {String} newjs The new js to run.
|
||||
*/
|
||||
var updatePage = function(newhtml, newjs) {
|
||||
$('[data-region="managetemplates"]').replaceWith(newhtml);
|
||||
|
@ -41,6 +42,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
/**
|
||||
* Callback to render the page template again and update the page.
|
||||
*
|
||||
* @method reloadList
|
||||
* @param {Object} context The context for the template.
|
||||
*/
|
||||
var reloadList = function(context) {
|
||||
|
@ -51,6 +53,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
|
||||
/**
|
||||
* Delete a template and reload the page.
|
||||
* @method doDelete
|
||||
*/
|
||||
var doDelete = function() {
|
||||
|
||||
|
@ -67,6 +70,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
|
||||
/**
|
||||
* Handler for "Delete learning plan template" actions.
|
||||
* @method confirmDelete
|
||||
* @param {Event} e
|
||||
*/
|
||||
var confirmDelete = function(e) {
|
||||
|
@ -81,7 +85,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
}]);
|
||||
|
||||
requests[0].done(function(template) {
|
||||
var strings = str.get_strings([
|
||||
str.get_strings([
|
||||
{ key: 'confirm', component: 'tool_lp' },
|
||||
{ key: 'deletetemplate', component: 'tool_lp', param: template.shortname },
|
||||
{ key: 'delete', component: 'tool_lp' },
|
||||
|
@ -100,19 +104,14 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'
|
|||
};
|
||||
|
||||
|
||||
return {
|
||||
return /** @alias module:tool_lp/templatedelete */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialise this plugin. Just attaches some event handlers to the delete entries in the menu.
|
||||
* Expose the event handler for the delete.
|
||||
* @method deleteHandler
|
||||
* @param {Event} e
|
||||
*/
|
||||
init: function() {
|
||||
// Init this module.
|
||||
$('[data-region="managetemplates"]').on(
|
||||
"click",
|
||||
'[data-action="deletetemplate"]',
|
||||
confirmDelete
|
||||
);
|
||||
}
|
||||
deleteHandler: confirmDelete
|
||||
|
||||
};
|
||||
});
|
||||
|
|
|
@ -21,17 +21,18 @@
|
|||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/dragdrop-reorder',
|
||||
define(['jquery',
|
||||
'core/str',
|
||||
'core/notification',
|
||||
'jquery',
|
||||
'core/ajax'],
|
||||
function(dragdrop, str, notification, $, ajax) {
|
||||
'core/ajax',
|
||||
'tool_lp/dragdrop-reorder'],
|
||||
function($, str, notification, ajax, dragdrop) {
|
||||
// Private variables and functions.
|
||||
|
||||
/**
|
||||
* Handle a drop on a node.
|
||||
*
|
||||
* @method handleDrop
|
||||
* @param {DOMNode} drag
|
||||
* @param {DOMNode} drop
|
||||
*/
|
||||
|
@ -47,10 +48,11 @@ define(['core/dragdrop-reorder',
|
|||
|
||||
};
|
||||
|
||||
return {
|
||||
return /** @alias module:tool_lp/templatemove */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialise this plugin. It loads some strings, then adds the drag/drop functions.
|
||||
* @method init
|
||||
*/
|
||||
init: function() {
|
||||
// Init this module.
|
||||
|
|
460
admin/tool/lp/amd/src/tree.js
Normal file
460
admin/tool/lp/amd/src/tree.js
Normal file
|
@ -0,0 +1,460 @@
|
|||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Implement an accessible aria tree widget, from a nested unordered list.
|
||||
* Based on http://oaa-accessibility.org/example/41/
|
||||
*
|
||||
* @module tool_lp/tree
|
||||
* @package core
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/url'], function($, url) {
|
||||
// Private variables and functions.
|
||||
/** @var {String} expandedImage The html for an expanded tree node twistie. */
|
||||
var expandedImage = $('<img alt="" src="' + url.imageUrl('t/expanded') + '"/>');
|
||||
/** @var {String} collapsedImage The html for a collapsed tree node twistie. */
|
||||
var collapsedImage = $('<img alt="" src="' + url.imageUrl('t/collapsed') + '"/>');
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {String} selector
|
||||
* @param {function} selectCallback Called when the active node is changed.
|
||||
*/
|
||||
var Tree = function(selector, selectCallback) {
|
||||
this.treeRoot = $(selector);
|
||||
|
||||
this.items = this.treeRoot.find('li');
|
||||
this.parents = this.treeRoot.find('li:has(ul)');
|
||||
|
||||
this.visibleItems = null;
|
||||
this.activeItem = null;
|
||||
this.selectCallback = selectCallback;
|
||||
|
||||
this.keys = {
|
||||
tab: 9,
|
||||
enter: 13,
|
||||
space: 32,
|
||||
pageup: 33,
|
||||
pagedown: 34,
|
||||
end: 35,
|
||||
home: 36,
|
||||
left: 37,
|
||||
up: 38,
|
||||
right: 39,
|
||||
down: 40,
|
||||
asterisk: 106
|
||||
};
|
||||
|
||||
this.init();
|
||||
|
||||
this.bindEventHandlers();
|
||||
};
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Init this tree
|
||||
* @method init
|
||||
*/
|
||||
Tree.prototype.init = function() {
|
||||
this.parents.attr('aria-expanded', 'true');
|
||||
this.parents.prepend(expandedImage.clone());
|
||||
|
||||
this.items.attr('role', 'tree-item');
|
||||
this.items.attr('tabindex', '-1');
|
||||
this.parents.attr('role', 'group');
|
||||
this.treeRoot.attr('role', 'tree');
|
||||
|
||||
this.visibleItems = this.treeRoot.find('li');
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a collapsed group.
|
||||
*
|
||||
* @method expandGroup
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
*/
|
||||
Tree.prototype.expandGroup = function(item) {
|
||||
// Find the first child ul node.
|
||||
var group = item.children('ul');
|
||||
|
||||
// Expand the group.
|
||||
group.show().attr('aria-hidden', 'false');
|
||||
|
||||
item.attr('aria-expanded', 'true');
|
||||
|
||||
item.children('img').attr('src', expandedImage.attr('src'));
|
||||
|
||||
// Update the list of visible items.
|
||||
this.visibleItems = this.treeRoot.find('li:visible');
|
||||
};
|
||||
|
||||
/**
|
||||
* Collapse an expanded group.
|
||||
*
|
||||
* @method collapseGroup
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
*/
|
||||
Tree.prototype.collapseGroup = function(item) {
|
||||
var group = item.children('ul');
|
||||
|
||||
// Collapse the group.
|
||||
group.hide().attr('aria-hidden', 'true');
|
||||
|
||||
item.attr('aria-expanded', 'false');
|
||||
|
||||
item.children('img').attr('src', collapsedImage.attr('src'));
|
||||
|
||||
// Update the list of visible items.
|
||||
this.visibleItems = this.treeRoot.find('li:visible');
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand or collapse a group.
|
||||
*
|
||||
* @method toggleGroup
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
*/
|
||||
Tree.prototype.toggleGroup = function(item) {
|
||||
if (item.attr('aria-expanded') == 'true') {
|
||||
this.collapseGroup(item);
|
||||
} else {
|
||||
this.expandGroup(item);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the focus to this item.
|
||||
*
|
||||
* @method updateFocus
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
*/
|
||||
Tree.prototype.updateFocus = function(item) {
|
||||
this.items.attr('aria-selected', 'false').attr('tabindex', '-1');
|
||||
item.attr('aria-selected', 'true').attr('tabindex', 0);
|
||||
this.selectCallback(item);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a key down event - ie navigate the tree.
|
||||
*
|
||||
* @method handleKeyDown
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleKeyDown = function(item, e) {
|
||||
var currentIndex = this.visibleItems.index(item);
|
||||
|
||||
if ((e.altKey || e.ctrlKey) || (e.shiftKey && e.keyCode != this.keys.tab)) {
|
||||
// Do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
case this.keys.home: {
|
||||
// Jump to first item in tree.
|
||||
this.activeItem = this.parents.first();
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.end: {
|
||||
// Jump to last visible item.
|
||||
this.activeItem = this.visibleItems.last();
|
||||
|
||||
this.activeItem.focus();
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.enter:
|
||||
case this.keys.space: {
|
||||
|
||||
if (item.has('ul')) {
|
||||
this.toggleGroup(item, true);
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.left: {
|
||||
if (item.has('ul') && item.attr('aria-expanded') == 'true') {
|
||||
this.collapseGroup(item);
|
||||
} else {
|
||||
// Move up to the parent.
|
||||
var itemUL = item.parent();
|
||||
var itemParent = itemUL.parent();
|
||||
|
||||
this.activeItem = itemParent;
|
||||
|
||||
this.activeItem.focus();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.right: {
|
||||
if (item.has('ul') && item.attr('aria-expanded') == 'false') {
|
||||
this.expandGroup(item);
|
||||
} else {
|
||||
// Move to the first item in the child group.
|
||||
this.activeItem = item.children('ul').children('li').first();
|
||||
|
||||
this.activeItem.focus();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.up: {
|
||||
|
||||
if (currentIndex > 0) {
|
||||
var prev = this.visibleItems.eq(currentIndex - 1);
|
||||
|
||||
this.activeItem = prev;
|
||||
|
||||
prev.focus();
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.down: {
|
||||
|
||||
if (currentIndex < this.visibleItems.length - 1) {
|
||||
var next = this.visibleItems.eq(currentIndex + 1);
|
||||
|
||||
this.activeItem = next;
|
||||
next.focus();
|
||||
}
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
case this.keys.asterisk: {
|
||||
// Expand all groups.
|
||||
|
||||
var thisObj = this;
|
||||
|
||||
this.parents.each(function() {
|
||||
thisObj.expandGroup($(this));
|
||||
});
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a key press event - ie navigate the tree.
|
||||
*
|
||||
* @method handleKeyPress
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleKeyPress = function(item, e) {
|
||||
if (e.altKey || e.ctrlKey || e.shiftKey) {
|
||||
// Do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
case this.keys.tab: {
|
||||
return true;
|
||||
}
|
||||
case this.keys.enter:
|
||||
case this.keys.home:
|
||||
case this.keys.end:
|
||||
case this.keys.left:
|
||||
case this.keys.right:
|
||||
case this.keys.up:
|
||||
case this.keys.down: {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
default : {
|
||||
var chr = String.fromCharCode(e.which);
|
||||
var match = false;
|
||||
var itemIndex = this.visibleItems.index(item);
|
||||
var itemCount = this.visibleItems.length;
|
||||
var currentIndex = itemIndex + 1;
|
||||
|
||||
// Check if the active item was the last one on the list.
|
||||
if (currentIndex == itemCount) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
|
||||
// Iterate through the menu items (starting from the current item and wrapping) until a match is found
|
||||
// or the loop returns to the current menu item.
|
||||
while (currentIndex != itemIndex) {
|
||||
|
||||
var currentItem = this.visibleItems.eq(currentIndex);
|
||||
var titleChr = currentItem.text().charAt(0);
|
||||
|
||||
if (currentItem.has('ul')) {
|
||||
titleChr = currentItem.find('span').text().charAt(0);
|
||||
}
|
||||
|
||||
if (titleChr.toLowerCase() == chr) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
currentIndex = currentIndex+1;
|
||||
if (currentIndex == itemCount) {
|
||||
// Reached the end of the list, start again at the beginning.
|
||||
currentIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (match === true) {
|
||||
this.activeItem = this.visibleItems.eq(currentIndex);
|
||||
this.activeItem.focus();
|
||||
}
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a double click (expand/collapse).
|
||||
*
|
||||
* @method handleDblClick
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleDblClick = function(item, e) {
|
||||
|
||||
if (e.altKey || e.ctrlKey || e.shiftKey) {
|
||||
// Do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update the active item.
|
||||
this.activeItem = item;
|
||||
|
||||
// Apply the focus markup.
|
||||
this.updateFocus(item);
|
||||
|
||||
// Expand or collapse the group.
|
||||
this.toggleGroup(item);
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a click (select).
|
||||
*
|
||||
* @method handleClick
|
||||
* @param {Object} item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleClick = function(item, e) {
|
||||
|
||||
if (e.altKey || e.ctrlKey || e.shiftKey) {
|
||||
// Do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update the active item.
|
||||
this.activeItem = item;
|
||||
|
||||
this.updateFocus(item);
|
||||
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a blur event
|
||||
*
|
||||
* @method handleBlur
|
||||
* @param {Object} item item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleBlur = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a focus event
|
||||
*
|
||||
* @method handleFocus
|
||||
* @param {Object} item item is the jquery id of the parent item of the group
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
Tree.prototype.handleFocus = function(item) {
|
||||
|
||||
if (this.activeItem === null) {
|
||||
this.activeItem = item;
|
||||
}
|
||||
|
||||
this.updateFocus(this.activeItem);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind the event listeners we require.
|
||||
*
|
||||
* @method bindEventHandlers
|
||||
*/
|
||||
Tree.prototype.bindEventHandlers = function() {
|
||||
var thisObj = this;
|
||||
|
||||
// Bind a dblclick handler to the parent items.
|
||||
this.parents.dblclick(function(e) {
|
||||
return thisObj.handleDblClick($(this), e);
|
||||
});
|
||||
|
||||
// Bind a click handler.
|
||||
this.items.click(function(e) {
|
||||
return thisObj.handleClick($(this), e);
|
||||
});
|
||||
|
||||
// Bind a keydown handler.
|
||||
this.items.keydown(function(e) {
|
||||
return thisObj.handleKeyDown($(this), e);
|
||||
});
|
||||
|
||||
// Bind a keypress handler.
|
||||
this.items.keypress(function(e) {
|
||||
return thisObj.handleKeyPress($(this), e);
|
||||
});
|
||||
|
||||
// Bind a focus handler.
|
||||
this.items.focus(function(e) {
|
||||
return thisObj.handleFocus($(this), e);
|
||||
});
|
||||
|
||||
// Bind a blur handler.
|
||||
this.items.blur(function(e) {
|
||||
return thisObj.handleBlur($(this), e);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return /** @alias module:tool_lp/tree */ Tree;
|
||||
});
|
|
@ -1,25 +1,14 @@
|
|||
.path-admin-tool-learningplan [data-region="managecompetencies"] ul li,
|
||||
.path-admin-tool-learningplan [data-region="plans"] ul li,
|
||||
.path-admin-tool-learningplan [data-region="competencymovetree"] ul li,
|
||||
.path-admin-tool-learningplan [data-region="competencylinktree"] ul li {
|
||||
.path-admin-tool-lp [data-region="managecompetencies"] ul li,
|
||||
.path-admin-tool-lp [data-region="plans"] ul li,
|
||||
.path-admin-tool-lp [data-region="competencymovetree"] ul li,
|
||||
.path-admin-tool-lp [data-region="competencylinktree"] ul li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.path-admin-tool-learningplan [data-region="managecompetencies"] ul li img,
|
||||
.path-admin-tool-learningplan [data-region="plans"] ul li img {
|
||||
margin-left: -20px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.dir-rtl.path-admin-tool-learningplan [data-region="plans"] ul li img,
|
||||
.dir-rtl.path-admin-tool-learningplan [data-region="managecompetencies"] ul li img {
|
||||
margin-right: -20px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.path-admin-tool-learningplan [data-region="managecompetencies"] ul[data-enhance="tree"],
|
||||
.path-admin-tool-learningplan [data-region="plans"] ul[data-enhance="tree"],
|
||||
.path-admin-tool-learningplan [data-region="competencylinktree"] ul[data-enhance="linktree"],
|
||||
.path-admin-tool-learningplan [data-region="competencymovetree"] ul[data-enhance="movetree"] {
|
||||
.path-admin-tool-lp [data-region="managecompetencies"] ul[data-enhance="tree"],
|
||||
.path-admin-tool-lp [data-region="plans"] ul[data-enhance="tree"],
|
||||
.path-admin-tool-lp [data-region="competencylinktree"] ul[data-enhance="linktree"],
|
||||
.path-admin-tool-lp [data-region="competencymovetree"] ul[data-enhance="movetree"] {
|
||||
border: 1px solid #ccc;
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
|
||||
transition: border linear .2s,box-shadow linear .2s;
|
||||
|
@ -29,37 +18,84 @@
|
|||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.path-admin-tool-learningplan [data-region="managecompetencies"] ul,
|
||||
.path-admin-tool-learningplan [data-region="plans"] ul,
|
||||
.path-admin-tool-learningplan [data-region="competencylinktree"] ul,
|
||||
.path-admin-tool-learningplan [data-region="competencymovetree"] ul {
|
||||
.path-admin-tool-lp [data-region="managecompetencies"] ul,
|
||||
.path-admin-tool-lp [data-region="plans"] ul,
|
||||
.path-admin-tool-lp [data-region="competencylinktree"] ul,
|
||||
.path-admin-tool-lp [data-region="competencymovetree"] ul {
|
||||
cursor: pointer;
|
||||
}
|
||||
.path-admin-tool-learningplan [data-region="competencylinktree"] ul [aria-selected="true"],
|
||||
.path-admin-tool-learningplan [data-region="competencymovetree"] ul [aria-selected="true"],
|
||||
.path-admin-tool-learningplan [data-region="plans"] ul [aria-selected="true"],
|
||||
.path-admin-tool-learningplan [data-region="managecompetencies"] ul [aria-selected="true"] {
|
||||
.path-admin-tool-lp [data-region="competencylinktree"] ul [aria-selected="true"],
|
||||
.path-admin-tool-lp [data-region="competencymovetree"] ul [aria-selected="true"],
|
||||
.path-admin-tool-lp [data-region="plans"] ul [aria-selected="true"],
|
||||
.path-admin-tool-lp [data-region="managecompetencies"] ul [aria-selected="true"] {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
.path-admin-tool-learningplan [data-region="filtercompetencies"] input {
|
||||
.path-admin-tool-lp [data-region="filtercompetencies"] input {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.path-admin-tool-learningplan [data-region="link-buttons"],
|
||||
.path-admin-tool-learningplan [data-region="move-buttons"] {
|
||||
.path-admin-tool-lp [data-region="link-buttons"],
|
||||
.path-admin-tool-lp [data-region="move-buttons"] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dir-rtl.path-admin-tool-learningplan [data-region="filtercompetencies"] input {
|
||||
.dir-rtl.path-admin-tool-lp [data-region="filtercompetencies"] input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.path-admin-tool-learningplan [data-region="competencyactionsmenu"] {
|
||||
display: none;
|
||||
}
|
||||
.path-admin-tool-learningplan [data-region="competencyactionsmenu"] .moodle-actionmenu[data-enhanced].show .menu {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.path-admin-tool-learningplan .currentdragtarget {
|
||||
.path-admin-tool-lp .currentdragtarget {
|
||||
border: 1px dashed;
|
||||
}
|
||||
|
||||
.path-admin-tool-lp .competencyactionsmenu {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
/** Styles required for menubar js */
|
||||
|
||||
.tool-lp-menu li {
|
||||
float: left;
|
||||
display: inline; position: relative;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.tool-lp-sub-menu {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
.tool-lp-sub-menu li {
|
||||
float: none;
|
||||
}
|
||||
.tool-lp-menu .tool-lp-sub-menu[aria-hidden=false] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tool-lp-menu ul[aria-hidden=true] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tool-lp-menu .caret {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.tool-lp-menu.tool-lp-menu-open-left .tool-lp-sub-menu {
|
||||
margin-left: -120px;
|
||||
}
|
||||
|
||||
.dir-rtl .tool-lp-menu.tool-lp-menu-open-left .tool-lp-sub-menu {
|
||||
margin-left: 0px;
|
||||
margin-right: -120px;
|
||||
}
|
||||
|
||||
/** This highlighting is copied from bootstrap - but can be overridden by a theme */
|
||||
.tool-lp-menu .tool-lp-sub-menu .menu-focus a {
|
||||
color: #fff ;
|
||||
text-decoration: none;
|
||||
background-color: #00699e;
|
||||
background-image: linear-gradient(to bottom,#0070a8,#005f8f);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
Classes required for JS:
|
||||
|
||||
Data attibutes required for JS:
|
||||
* data-enhance=tree
|
||||
* data-enhance=movetree
|
||||
|
||||
Context variables required for this template:
|
||||
* framework -
|
||||
|
|
|
@ -56,51 +56,54 @@
|
|||
</p>
|
||||
{{#canmanage}}
|
||||
<div data-region="competencyactions">
|
||||
<div class="btn-group">
|
||||
<button class="btn" data-action="add" disabled="disabled">{{#pix}}t/add{{/pix}} {{#str}}addcompetency, tool_lp{{/str}}</button>
|
||||
</div>
|
||||
<div data-region="competencyactionsmenu">
|
||||
<ul class="competencyactionsmenu">
|
||||
<span data-region="competencyactionsmenu">
|
||||
<ul title="{{#str}}edit{{/str}}" class="competencyactionsmenu">
|
||||
<li>
|
||||
<a href="#" data-action="edit">
|
||||
{{#pix}}t/edit{{/pix}}{{#str}}edit{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="move">
|
||||
{{#pix}}t/move{{/pix}}{{#str}}movetonewparent, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="delete">
|
||||
{{#pix}}t/delete{{/pix}}{{#str}}delete{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="moveup">
|
||||
{{#pix}}t/up{{/pix}}{{#str}}moveup{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="movedown">
|
||||
{{#pix}}t/down{{/pix}}{{#str}}movedown{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="linkedcourses">
|
||||
{{#pix}}t/viewdetails{{/pix}}{{#str}}linkedcourses, tool_lp{{/str}}
|
||||
</a>
|
||||
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#" data-action="edit">
|
||||
{{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="move">
|
||||
{{#pix}}t/move{{/pix}} {{#str}}movetonewparent, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="delete">
|
||||
{{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="moveup">
|
||||
{{#pix}}t/up{{/pix}} {{#str}}moveup{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="movedown">
|
||||
{{#pix}}t/down{{/pix}} {{#str}}movedown{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" data-action="linkedcourses">
|
||||
{{#pix}}t/viewdetails{{/pix}} {{#str}}linkedcourses, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/canmanage}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
// Initialise the JS.
|
||||
require(['core/tree', 'tool_lp/competencytree', 'tool_lp/competencyactions' ], function(ariatree, treeModel, actions) {
|
||||
require(['tool_lp/tree', 'tool_lp/competencytree', 'tool_lp/competencyactions' ], function(ariatree, treeModel, actions) {
|
||||
|
||||
treeModel.init({{framework.id}});
|
||||
|
||||
|
|
|
@ -50,20 +50,23 @@
|
|||
<td>{{competencies_count}}</td>
|
||||
<td>
|
||||
{{#canmanage}}
|
||||
<div style="display: inline-block;">
|
||||
<ul class="competencyframeworkactions hide">
|
||||
<ul title="{{#str}}edit{{/str}}" class="competencyframeworkactions">
|
||||
<li>
|
||||
<a href="{{pluginbaseurl}}/editcompetencyframework.php?id={{id}}">
|
||||
{{#pix}}t/edit{{/pix}}{{#str}}editthiscompetencyframework, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-action="deletecompetencyframework" data-frameworkid="{{id}}" href="#">
|
||||
{{#pix}}t/delete{{/pix}}{{#str}}deletethiscompetencyframework, tool_lp{{/str}}
|
||||
</a>
|
||||
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="{{pluginbaseurl}}/editcompetencyframework.php?id={{id}}">
|
||||
{{#pix}}t/edit{{/pix}} {{#str}}editthiscompetencyframework, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-action="deletecompetencyframework" data-frameworkid="{{id}}" href="#">
|
||||
{{#pix}}t/delete{{/pix}} {{#str}}deletethiscompetencyframework, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/canmanage}}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -85,14 +88,15 @@
|
|||
{{#js}}
|
||||
// Initialise the JS.
|
||||
require(['tool_lp/frameworkdelete',
|
||||
'core/menu',
|
||||
'tool_lp/menubar',
|
||||
'tool_lp/frameworkmove'],
|
||||
function(deleteMod, menu, moveMod) {
|
||||
function(deleteMod, menubar, moveMod) {
|
||||
|
||||
deleteMod.init();
|
||||
moveMod.init();
|
||||
|
||||
menu.menu('{{#str}}edit{{/str}}', '.competencyframeworkactions');
|
||||
menubar.enhance('.competencyframeworkactions', {
|
||||
"[data-action='deletecompetencyframework']": deleteMod.deleteHandler
|
||||
});
|
||||
});
|
||||
|
||||
{{/js}}
|
||||
|
|
|
@ -48,20 +48,23 @@
|
|||
<td><span class="drag-handlecontainer"></span><span><a href="{{pluginbaseurl}}/templatecompetencies.php?templateid={{id}}">{{shortname}} {{idnumber}}</a></span> {{^visible}}{{#str}}hiddenhint, tool_lp{{/str}}{{/visible}}</td>
|
||||
<td>
|
||||
{{#canmanage}}
|
||||
<div style="display: inline-block;">
|
||||
<ul class="templateactions hide">
|
||||
<ul class="templateactions">
|
||||
<li>
|
||||
<a href="{{pluginbaseurl}}/edittemplate.php?id={{id}}">
|
||||
{{#pix}}t/edit{{/pix}}{{#str}}editthistemplate, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-action="deletetemplate" data-templateid="{{id}}" href="#">
|
||||
{{#pix}}t/delete{{/pix}}{{#str}}deletethistemplate, tool_lp{{/str}}
|
||||
</a>
|
||||
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="{{pluginbaseurl}}/edittemplate.php?id={{id}}">
|
||||
{{#pix}}t/edit{{/pix}} {{#str}}editthistemplate, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-action="deletetemplate" data-templateid="{{id}}" href="#">
|
||||
{{#pix}}t/delete{{/pix}} {{#str}}deletethistemplate, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/canmanage}}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -83,14 +86,15 @@
|
|||
{{#js}}
|
||||
// Initialise the JS.
|
||||
require(['tool_lp/templatedelete',
|
||||
'core/menu',
|
||||
'tool_lp/menubar',
|
||||
'tool_lp/templatemove'],
|
||||
function(deleteMod, menu, moveMod) {
|
||||
function(deleteMod, menubar, moveMod) {
|
||||
|
||||
deleteMod.init();
|
||||
moveMod.init();
|
||||
|
||||
menu.menu('{{#str}}edit{{/str}}', '.templateactions');
|
||||
menubar.enhance('.templateactions', {
|
||||
'[data-action="deletetemplate"]': deleteMod.deleteHandler
|
||||
});
|
||||
});
|
||||
|
||||
{{/js}}
|
||||
|
|
72
admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder-debug.js
vendored
Normal file
72
admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder-debug.js
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
YUI.add('moodle-tool_lp-dragdrop-reorder', function (Y, NAME) {
|
||||
|
||||
/**
|
||||
* Simple drag and drop.
|
||||
*
|
||||
* Used when we just want a list of things that can be re-ordered by dragging.
|
||||
*
|
||||
* @class M.tool_lp.dragdrop_reorder
|
||||
* @constructor
|
||||
* @extends M.core.dragdrop
|
||||
*/
|
||||
var DRAGREORDER = function() {
|
||||
DRAGREORDER.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
|
||||
var CSS = {
|
||||
EDITINGMOVE: 'editing_move',
|
||||
ICONCLASS: 'iconsmall'
|
||||
};
|
||||
Y.extend(DRAGREORDER, M.core.dragdrop, {
|
||||
initializer: function(args) {
|
||||
if (Y.one('.' + args.parentNodeClass).all('.' + args.dragHandleInsertClass).size() <= 1) {
|
||||
// We can't re-order when there is only one item.
|
||||
return;
|
||||
}
|
||||
// Set group for parent class
|
||||
this.groups = [args.group];
|
||||
this.samenodeclass = args.sameNodeClass;
|
||||
this.parentnodeclass = args.parentNodeClass;
|
||||
this.draghandleinsertclass = args.dragHandleInsertClass;
|
||||
this.draghandle = this.get_drag_handle(args.dragHandleText,
|
||||
CSS.EDITINGMOVE, CSS.ICONCLASS, true);
|
||||
|
||||
this.samenodelabel = args.sameNodeLabel;
|
||||
this.parentnodelabel = args.parentNodeLabel;
|
||||
this.callback = args.callback;
|
||||
|
||||
var delegate = new Y.DD.Delegate({
|
||||
container: '.' + args.parentNodeClass,
|
||||
nodes: '.' + args.sameNodeClass,
|
||||
target: true,
|
||||
handles: ['.' + CSS.EDITINGMOVE],
|
||||
dragConfig: {groups: this.groups}
|
||||
});
|
||||
|
||||
delegate.dd.plug(Y.Plugin.DDProxy);
|
||||
|
||||
Y.one('.' + args.parentNodeClass)
|
||||
.all('.' + args.dragHandleInsertClass)
|
||||
.each(
|
||||
function (node) {
|
||||
node.insert(this.draghandle.cloneNode(true));
|
||||
} , this);
|
||||
},
|
||||
|
||||
drop_hit: function(e) {
|
||||
this.callback(e);
|
||||
}
|
||||
|
||||
}, {
|
||||
NAME: 'tool_lp-dragdrop-reorder',
|
||||
ATTRS: {
|
||||
}
|
||||
});
|
||||
|
||||
M.tool_lp = M.tool_lp || {};
|
||||
M.tool_lp.dragdrop_reorder = function(params) {
|
||||
new DRAGREORDER(params);
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["moodle-core-dragdrop"]});
|
|
@ -0,0 +1 @@
|
|||
YUI.add("moodle-tool_lp-dragdrop-reorder",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r={EDITINGMOVE:"editing_move",ICONCLASS:"iconsmall"};e.extend(n,M.core.dragdrop,{initializer:function(t){if(e.one("."+t.parentNodeClass).all("."+t.dragHandleInsertClass).size()<=1)return;this.groups=[t.group],this.samenodeclass=t.sameNodeClass,this.parentnodeclass=t.parentNodeClass,this.draghandleinsertclass=t.dragHandleInsertClass,this.draghandle=this.get_drag_handle(t.dragHandleText,r.EDITINGMOVE,r.ICONCLASS,!0),this.samenodelabel=t.sameNodeLabel,this.parentnodelabel=t.parentNodeLabel,this.callback=t.callback;var n=new e.DD.Delegate({container:"."+t.parentNodeClass,nodes:"."+t.sameNodeClass,target:!0,handles:["."+r.EDITINGMOVE],dragConfig:{groups:this.groups}});n.dd.plug(e.Plugin.DDProxy),e.one("."+t.parentNodeClass).all("."+t.dragHandleInsertClass).each(function(e){e.insert(this.draghandle.cloneNode(!0))},this)},drop_hit:function(e){this.callback(e)}},{NAME:"tool_lp-dragdrop-reorder",ATTRS:{}}),M.tool_lp=M.tool_lp||{},M.tool_lp.dragdrop_reorder=function(e){new n(e)}},"@VERSION@",{requires:["moodle-core-dragdrop"]});
|
72
admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder.js
vendored
Normal file
72
admin/tool/lp/yui/build/moodle-tool_lp-dragdrop-reorder/moodle-tool_lp-dragdrop-reorder.js
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
YUI.add('moodle-tool_lp-dragdrop-reorder', function (Y, NAME) {
|
||||
|
||||
/**
|
||||
* Simple drag and drop.
|
||||
*
|
||||
* Used when we just want a list of things that can be re-ordered by dragging.
|
||||
*
|
||||
* @class M.tool_lp.dragdrop_reorder
|
||||
* @constructor
|
||||
* @extends M.core.dragdrop
|
||||
*/
|
||||
var DRAGREORDER = function() {
|
||||
DRAGREORDER.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
|
||||
var CSS = {
|
||||
EDITINGMOVE: 'editing_move',
|
||||
ICONCLASS: 'iconsmall'
|
||||
};
|
||||
Y.extend(DRAGREORDER, M.core.dragdrop, {
|
||||
initializer: function(args) {
|
||||
if (Y.one('.' + args.parentNodeClass).all('.' + args.dragHandleInsertClass).size() <= 1) {
|
||||
// We can't re-order when there is only one item.
|
||||
return;
|
||||
}
|
||||
// Set group for parent class
|
||||
this.groups = [args.group];
|
||||
this.samenodeclass = args.sameNodeClass;
|
||||
this.parentnodeclass = args.parentNodeClass;
|
||||
this.draghandleinsertclass = args.dragHandleInsertClass;
|
||||
this.draghandle = this.get_drag_handle(args.dragHandleText,
|
||||
CSS.EDITINGMOVE, CSS.ICONCLASS, true);
|
||||
|
||||
this.samenodelabel = args.sameNodeLabel;
|
||||
this.parentnodelabel = args.parentNodeLabel;
|
||||
this.callback = args.callback;
|
||||
|
||||
var delegate = new Y.DD.Delegate({
|
||||
container: '.' + args.parentNodeClass,
|
||||
nodes: '.' + args.sameNodeClass,
|
||||
target: true,
|
||||
handles: ['.' + CSS.EDITINGMOVE],
|
||||
dragConfig: {groups: this.groups}
|
||||
});
|
||||
|
||||
delegate.dd.plug(Y.Plugin.DDProxy);
|
||||
|
||||
Y.one('.' + args.parentNodeClass)
|
||||
.all('.' + args.dragHandleInsertClass)
|
||||
.each(
|
||||
function (node) {
|
||||
node.insert(this.draghandle.cloneNode(true));
|
||||
} , this);
|
||||
},
|
||||
|
||||
drop_hit: function(e) {
|
||||
this.callback(e);
|
||||
}
|
||||
|
||||
}, {
|
||||
NAME: 'tool_lp-dragdrop-reorder',
|
||||
ATTRS: {
|
||||
}
|
||||
});
|
||||
|
||||
M.tool_lp = M.tool_lp || {};
|
||||
M.tool_lp.dragdrop_reorder = function(params) {
|
||||
new DRAGREORDER(params);
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["moodle-core-dragdrop"]});
|
10
admin/tool/lp/yui/src/dragdrop-reorder/build.json
Normal file
10
admin/tool/lp/yui/src/dragdrop-reorder/build.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "moodle-tool_lp-dragdrop-reorder",
|
||||
"builds": {
|
||||
"moodle-tool_lp-dragdrop-reorder": {
|
||||
"jsfiles": [
|
||||
"dragdropreorder.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
67
admin/tool/lp/yui/src/dragdrop-reorder/js/dragdropreorder.js
vendored
Normal file
67
admin/tool/lp/yui/src/dragdrop-reorder/js/dragdropreorder.js
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Simple drag and drop.
|
||||
*
|
||||
* Used when we just want a list of things that can be re-ordered by dragging.
|
||||
*
|
||||
* @class M.tool_lp.dragdrop_reorder
|
||||
* @constructor
|
||||
* @extends M.core.dragdrop
|
||||
*/
|
||||
var DRAGREORDER = function() {
|
||||
DRAGREORDER.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
|
||||
var CSS = {
|
||||
EDITINGMOVE: 'editing_move',
|
||||
ICONCLASS: 'iconsmall'
|
||||
};
|
||||
Y.extend(DRAGREORDER, M.core.dragdrop, {
|
||||
initializer: function(args) {
|
||||
if (Y.one('.' + args.parentNodeClass).all('.' + args.dragHandleInsertClass).size() <= 1) {
|
||||
// We can't re-order when there is only one item.
|
||||
return;
|
||||
}
|
||||
// Set group for parent class
|
||||
this.groups = [args.group];
|
||||
this.samenodeclass = args.sameNodeClass;
|
||||
this.parentnodeclass = args.parentNodeClass;
|
||||
this.draghandleinsertclass = args.dragHandleInsertClass;
|
||||
this.draghandle = this.get_drag_handle(args.dragHandleText,
|
||||
CSS.EDITINGMOVE, CSS.ICONCLASS, true);
|
||||
|
||||
this.samenodelabel = args.sameNodeLabel;
|
||||
this.parentnodelabel = args.parentNodeLabel;
|
||||
this.callback = args.callback;
|
||||
|
||||
var delegate = new Y.DD.Delegate({
|
||||
container: '.' + args.parentNodeClass,
|
||||
nodes: '.' + args.sameNodeClass,
|
||||
target: true,
|
||||
handles: ['.' + CSS.EDITINGMOVE],
|
||||
dragConfig: {groups: this.groups}
|
||||
});
|
||||
|
||||
delegate.dd.plug(Y.Plugin.DDProxy);
|
||||
|
||||
Y.one('.' + args.parentNodeClass)
|
||||
.all('.' + args.dragHandleInsertClass)
|
||||
.each(
|
||||
function (node) {
|
||||
node.insert(this.draghandle.cloneNode(true));
|
||||
} , this);
|
||||
},
|
||||
|
||||
drop_hit: function(e) {
|
||||
this.callback(e);
|
||||
}
|
||||
|
||||
}, {
|
||||
NAME: 'tool_lp-dragdrop-reorder',
|
||||
ATTRS: {
|
||||
}
|
||||
});
|
||||
|
||||
M.tool_lp = M.tool_lp || {};
|
||||
M.tool_lp.dragdrop_reorder = function(params) {
|
||||
new DRAGREORDER(params);
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"moodle-tool_lp-dragdrop-reorder": {
|
||||
"requires": [
|
||||
"moodle-core-dragdrop"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue