diff --git a/lib/amd/build/sortable_list.min.js b/lib/amd/build/sortable_list.min.js
index 57297b4363b..058c5e29467 100644
--- a/lib/amd/build/sortable_list.min.js
+++ b/lib/amd/build/sortable_list.min.js
@@ -1 +1 @@
-define(["jquery","core/log","core/autoscroll","core/str","core/modal_factory","core/modal_events","core/notification"],function(a,b,c,d,e,f,g){var h,i,j,k={targetListSelector:null,moveHandlerSelector:null,isHorizontal:!1,autoScroll:!0,elementNameCallback:function(a){return a.text()},destinationNameCallback:function(a,b){return b.length?D(b).then(function(a){return d.get_string("movecontentafter","moodle",a)}):d.get_string("movecontenttothetop","moodle")},moveDialogueTitleCallback:function(a){return D(a).then(function(a){return d.get_string("movecontent","moodle",a)})}},l={keyboardDragClass:"dragdrop-keyboard-drag",isDraggedClass:"sortable-list-is-dragged",currentPositionClass:"sortable-list-current-position",sourceListClass:"sortable-list-source",targetListClass:"sortable-list-target",overElementClass:"sortable-list-over-element"},m={},n=null,o=0,p=function(){var b=[m.isDraggedClass,m.currentPositionClass,m.overElementClass,m.targetListClass,m.sourceListClass];for(var c in b)a("."+b[c]).removeClass(b[c]);h&&(h.remove(),h=a())},q=function(b){if(b.originalEvent&&b.originalEvent.touches&&void 0!==b.originalEvent.touches[0]){var c=b.originalEvent.touches[0];b.pageX=c.pageX,b.pageY=c.pageY}void 0===b.pageX?(b.pageX=j.pageX,b.pageY=j.pageY):j=b,void 0===b.clientX&&(b.clientX=Math.round(b.pageX-a(window).scrollLeft()),b.clientY=Math.round(b.pageY-a(window).scrollTop()))},r=function(b){if(m=b.data.config,null!==n){if("click"===n.type)return;y(n.sourceList,n.sourceNextElement),z()}if("mousedown"!==b.type||1===b.which){q(b);var d=a(b.target).closest(a(b.currentTarget).children());if(d.length&&(null===m.moveHandlerSelector||a(b.target).closest(m.moveHandlerSelector,d).length)){b.stopPropagation(),b.preventDefault(),o++,n={element:d,sourceNextElement:d.next(),sourceList:d.parent(),targetNextElement:d.next(),targetList:d.parent(),type:b.type,dropped:!1,startX:b.pageX,startY:b.pageY,startTime:(new Date).getTime()},a(m.targetListSelector).addClass(m.targetListClass);var e=d.offset();d.addClass(m.currentPositionClass),i={x:e.left-b.pageX,y:e.top-b.pageY},h=a();var f=o;setTimeout(function(){null!==n&&"click"!==n.type&&"keypress"!==n.type&&o===f&&s()},500),a("body").on("mousemove touchmove mouseup touchend",x),a("body").on("keypress",B),m.autoScroll&&c.start(function(){a("body").trigger("mousemove")}),A("dragstart")}}},s=function(){h=n.element.clone(),n.sourceList.append(h),h.removeAttr("id").removeClass(m.currentPositionClass).addClass(m.isDraggedClass).css({position:"fixed"}),h.offset({top:i.y+j.pageY,left:i.x+j.pageX})},t=function(b){if(!("keypress"===b.type&&13!==b.originalEvent.keyCode&&32!==b.originalEvent.keyCode||null!==n&&"click"===n.type)){b.preventDefault(),b.stopPropagation(),m=b.data.config;var c=a(b.currentTarget).closest(m.listSelector),d=a(b.target).closest(c.children());d.length&&(o++,n={element:d,sourceNextElement:d.next(),sourceList:c,targetNextElement:d.next(),targetList:c,dropped:!1,type:b.type,startTime:(new Date).getTime()},A("dragstart"),H())}},u=function(a,b,c){if(!c.length)return null;var d=c[0],e=0,f=d.getBoundingClientRect(),g=b-(f.top+window.scrollY),h=a-(f.left+window.scrollX);return h>=-e&&h<=f.width+e&&g>=-e&&g<=f.height+e?{x:h,y:g,xRatio:f.width?h/f.width:0,yRatio:f.height?g/f.height:0}:null},v=function(){return!h||!h.length||this!==h[0]},w=function(a){var b=m.isHorizontal;return b===!0||b===!1?b:b(a)},x=function(b){q(b),h.offset({top:-1e3,left:-1e3});var c=a(document.elementFromPoint(b.clientX,b.clientY)),d=c.closest("."+m.targetListClass+" > :not(."+m.isDraggedClass+")"),e=c.closest("."+m.targetListClass);if(a("."+m.overElementClass).removeClass(m.overElementClass),d.addClass(m.overElementClass),h.offset({top:i.y+b.pageY,left:i.x+b.pageX}),e.length&&!e.children().filter(v).length)y(e,a());else if(1===d.length&&!n.element.find(d[0]).length){var f=u(b.pageX,b.pageY,d);if(f){var g=d.parent(),j=w(g)?f.xRatio:f.yRatio,k=d.find("."+m.targetListClass),l=function(){return this!==n.element[0]},o=!k.children().filter(v).filter(l).length;k.length&&o&&j>.2&&j<.8?y(k,a()):j>.5?y(g,d.next().filter(v)):y(g,d)}}"mouseup"!==b.type&&"touchend"!==b.type||(n.endX=b.pageX,n.endY=b.pageY,n.endTime=(new Date).getTime(),n.dropped=!0,A("drop"),z())},y=function(a,b){var c=n.element;b.length&&b[0]===c[0]||a[0]===n.targetList[0]&&b.length===n.targetNextElement.length&&b[0]===n.targetNextElement[0]||(b.length?a[0].insertBefore(c[0],b[0]):h&&h.parent().length&&h.parent()[0]===a[0]?a[0].insertBefore(c[0],h[0]):a[0].appendChild(c[0]),n.targetList=a,n.targetNextElement=b,A("drag"))},z=function(){p(),m.autoScroll&&c.stop(),a("body").off("mousemove touchmove mouseup touchend",x),a("body").off("keypress",B),A("dragend"),n=null},A=function(a){n.element.trigger("sortablelist-"+a,n)},B=function(a){"keypress"===a.type&&27===a.originalEvent.keyCode&&(y(n.sourceList,n.sourceNextElement),z())},C=function(b){var c=b;return"object"==typeof b&&b.hasOwnProperty("then")||(c=a.Deferred(),c.resolve(b)),c},D=function(a){return C(m.elementNameCallback(a))},E=function(a,b){return C(m.destinationNameCallback(a,b))},F=function(a){return C(m.moveDialogueTitleCallback(a))},G=function(b){var c=[],d=a(m.targetListSelector),e=a("
").addClass(m.keyboardDragClass),f=function(c,d,f){if(!d.is(n.element)&&!f.is(n.element)){var h=a("").appendTo(e),i=a('').on("click",function(a){a.preventDefault(),a.stopPropagation(),y(c,d),n.endTime=(new Date).getTime(),n.dropped=!0,n.element.find(m.moveHandlerSelector).focus(),A("drop"),b.hide()}).appendTo(h);E(c,f).then(function(a){return i.text(a),a})["catch"](g.exception)}},h=function(){if(a.inArray(this,c)===-1){c.push(this);var b=a(this),e=b.children();e.each(function(){var c=a(this);f(b,c,c.prev()),c.find(d).each(h)}),f(b,a(),e.last())}};return d.each(h),e},H=function(){e.create({type:e.types.CANCEL,title:F(n.element)}).then(function(a){return a.getRoot().on(f.hidden,function(){a.destroy(),z()}),a.getBody().append(G(a)),a.setLarge(),a.show(),a})["catch"](g.exception)};return{init:function(b,c){"undefined"!=typeof c&&c||(c={}),c=a.extend({},k,l,c),c.listSelector=b,c.targetListSelector||(c.targetListSelector=b),a("body").on("mousedown touchstart",c.listSelector,{config:c},r),null!==c.moveHandlerSelector&&a("body").on("click keypress",c.moveHandlerSelector,{config:c},t)}}});
\ No newline at end of file
+define(["jquery","core/log","core/autoscroll","core/str","core/modal_factory","core/modal_events","core/notification"],function(a,b,c,d,e,f,g){var h,i,j,k={targetListSelector:null,moveHandlerSelector:null,isHorizontal:!1,autoScroll:!0,elementNameCallback:function(a){return a.text()},destinationNameCallback:function(a,b){return b.length?D(b).then(function(a){return d.get_string("movecontentafter","moodle",a)}):d.get_string("movecontenttothetop","moodle")},moveDialogueTitleCallback:function(a){return D(a).then(function(a){return d.get_string("movecontent","moodle",a)})}},l={keyboardDragClass:"dragdrop-keyboard-drag",isDraggedClass:"sortable-list-is-dragged",currentPositionClass:"sortable-list-current-position",sourceListClass:"sortable-list-source",targetListClass:"sortable-list-target",overElementClass:"sortable-list-over-element"},m={},n=null,o=0,p=function(){var b=[m.isDraggedClass,m.currentPositionClass,m.overElementClass,m.targetListClass,m.sourceListClass];for(var c in b)a("."+b[c]).removeClass(b[c]);h&&(h.remove(),h=a())},q=function(b){if(b.originalEvent&&b.originalEvent.touches&&void 0!==b.originalEvent.touches[0]){var c=b.originalEvent.touches[0];b.pageX=c.pageX,b.pageY=c.pageY}void 0===b.pageX?(b.pageX=j.pageX,b.pageY=j.pageY):j=b,void 0===b.clientX&&(b.clientX=Math.round(b.pageX-a(window).scrollLeft()),b.clientY=Math.round(b.pageY-a(window).scrollTop()))},r=function(b){if(m=b.data.config,null!==n){if("click"===n.type)return;y(n.sourceList,n.sourceNextElement),z()}if("mousedown"!==b.type||1===b.which){q(b);var d=a(b.target).closest(a(b.currentTarget).children());if(d.length&&(null===m.moveHandlerSelector||a(b.target).closest(m.moveHandlerSelector,d).length)){b.stopPropagation(),b.preventDefault(),o++,n={element:d,sourceNextElement:d.next(),sourceList:d.parent(),targetNextElement:d.next(),targetList:d.parent(),type:b.type,dropped:!1,startX:b.pageX,startY:b.pageY,startTime:(new Date).getTime()},a(m.targetListSelector).addClass(m.targetListClass);var e=d.offset();d.addClass(m.currentPositionClass),i={x:e.left-b.pageX,y:e.top-b.pageY},h=a();var f=o;setTimeout(function(){null!==n&&"click"!==n.type&&"keypress"!==n.type&&o===f&&s()},500),a("body").on("mousemove touchmove mouseup touchend",x),a("body").on("keypress",B),m.autoScroll&&c.start(function(){a("body").trigger("mousemove")}),A("dragstart")}}},s=function(){h=n.element.clone(),n.sourceList.append(h),h.removeAttr("id").removeClass(m.currentPositionClass).addClass(m.isDraggedClass).css({position:"fixed"}),h.offset({top:i.y+j.pageY,left:i.x+j.pageX})},t=function(b){if(!("keypress"===b.type&&13!==b.originalEvent.keyCode&&32!==b.originalEvent.keyCode||null!==n&&"click"===n.type)){b.preventDefault(),b.stopPropagation(),m=b.data.config;var c=a(b.currentTarget),d=c.closest(m.listSelector),e=c.closest(d.children());e.length&&(o++,n={element:e,sourceNextElement:e.next(),sourceList:d,targetNextElement:e.next(),targetList:d,dropped:!1,type:b.type,startTime:(new Date).getTime()},A("dragstart"),H(c))}},u=function(a,b,c){if(!c.length)return null;var d=c[0],e=0,f=d.getBoundingClientRect(),g=b-(f.top+window.scrollY),h=a-(f.left+window.scrollX);return h>=-e&&h<=f.width+e&&g>=-e&&g<=f.height+e?{x:h,y:g,xRatio:f.width?h/f.width:0,yRatio:f.height?g/f.height:0}:null},v=function(){return!h||!h.length||this!==h[0]},w=function(a){var b=m.isHorizontal;return b===!0||b===!1?b:b(a)},x=function(b){q(b),h.offset({top:-1e3,left:-1e3});var c=a(document.elementFromPoint(b.clientX,b.clientY)),d=c.closest("."+m.targetListClass+" > :not(."+m.isDraggedClass+")"),e=c.closest("."+m.targetListClass);if(a("."+m.overElementClass).removeClass(m.overElementClass),d.addClass(m.overElementClass),h.offset({top:i.y+b.pageY,left:i.x+b.pageX}),e.length&&!e.children().filter(v).length)y(e,a());else if(1===d.length&&!n.element.find(d[0]).length){var f=u(b.pageX,b.pageY,d);if(f){var g=d.parent(),j=w(g)?f.xRatio:f.yRatio,k=d.find("."+m.targetListClass),l=function(){return this!==n.element[0]},o=!k.children().filter(v).filter(l).length;k.length&&o&&j>.2&&j<.8?y(k,a()):j>.5?y(g,d.next().filter(v)):y(g,d)}}"mouseup"!==b.type&&"touchend"!==b.type||(n.endX=b.pageX,n.endY=b.pageY,n.endTime=(new Date).getTime(),n.dropped=!0,A("drop"),z())},y=function(a,b){var c=n.element;b.length&&b[0]===c[0]||a[0]===n.targetList[0]&&b.length===n.targetNextElement.length&&b[0]===n.targetNextElement[0]||(b.length?a[0].insertBefore(c[0],b[0]):h&&h.parent().length&&h.parent()[0]===a[0]?a[0].insertBefore(c[0],h[0]):a[0].appendChild(c[0]),n.targetList=a,n.targetNextElement=b,A("drag"))},z=function(){p(),m.autoScroll&&c.stop(),a("body").off("mousemove touchmove mouseup touchend",x),a("body").off("keypress",B),A("dragend"),n=null},A=function(a){n.element.trigger("sortablelist-"+a,n)},B=function(a){"keypress"===a.type&&27===a.originalEvent.keyCode&&(y(n.sourceList,n.sourceNextElement),z())},C=function(b){var c=b;return"object"==typeof b&&b.hasOwnProperty("then")||(c=a.Deferred(),c.resolve(b)),c},D=function(a){return C(m.elementNameCallback(a))},E=function(a,b){return C(m.destinationNameCallback(a,b))},F=function(a){return C(m.moveDialogueTitleCallback(a))},G=function(){var b=[],c=a(m.targetListSelector),d=a("").addClass(m.keyboardDragClass),e=a.when().then(function(){return d}),f=function(b,c,f){c.is(n.element)||f.is(n.element)||(e=e.then(function(){return E(b,f)}).then(function(e){var f=a("").appendTo(d),g=a('').attr("data-sortable-quickmove",1).appendTo(f);return g.data("parent-element",b).data("before-element",c).text(e),d}))},g=function(){if(a.inArray(this,b)===-1){b.push(this);var d=a(this),e=d.children();e.each(function(){var b=a(this);f(d,b,b.prev()),b.find(c).each(g)}),f(d,a(),e.last())}};return c.each(g),e},H=function(b){e.create({type:e.types.CANCEL,title:F(n.element),body:G()}).then(function(c){var d=function(d){d.preventDefault(),d.stopPropagation(),y(a(d.currentTarget).data("parent-element"),a(d.currentTarget).data("before-element")),n.endTime=(new Date).getTime(),n.dropped=!0,b.focus(),A("drop"),c.hide()};return c.getRoot().on("click","[data-sortable-quickmove]",d),c.getRoot().on(f.hidden,function(){c.getRoot().off("click","[data-sortable-quickmove]",d),c.destroy(),z()}),c.setLarge(),c.show(),c})["catch"](g.exception)};return{init:function(b,c){c=a.extend({},k,l,c||{}),c.listSelector=b,c.targetListSelector||(c.targetListSelector=b),"object"==typeof c.listSelector?a(c.listSelector).on("mousedown touchstart",{config:c},r):a("body").on("mousedown touchstart",c.listSelector,{config:c},r),null!==c.moveHandlerSelector&&a("body").on("click keypress",c.moveHandlerSelector,{config:c},t)}}});
\ No newline at end of file
diff --git a/lib/amd/src/sortable_list.js b/lib/amd/src/sortable_list.js
index 78c1daa47de..d381912b84c 100644
--- a/lib/amd/src/sortable_list.js
+++ b/lib/amd/src/sortable_list.js
@@ -317,8 +317,9 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
config = evt.data.config;
// Find the element that this draghandle belongs to.
- var sourceList = $(evt.currentTarget).closest(config.listSelector),
- movedElement = $(evt.target).closest(sourceList.children());
+ var clickedElement = $(evt.currentTarget),
+ sourceList = clickedElement.closest(config.listSelector),
+ movedElement = clickedElement.closest(sourceList.children());
if (!movedElement.length) {
return;
}
@@ -337,7 +338,7 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
};
executeCallback('dragstart');
- displayMoveDialogue();
+ displayMoveDialogue(clickedElement);
};
/**
@@ -594,40 +595,36 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
};
/**
- * Returns the list of possible move destinations with their onclick handlers
+ * Returns the list of possible move destinations
*
* @private
- * @param {Modal} modal
- * @return {jQuery}
+ * @return {Promise}
*/
- var getDestinationsList = function(modal) {
+ var getDestinationsList = function() {
var addedLists = [],
targets = $(config.targetListSelector),
- list = $('').addClass(config.keyboardDragClass),
+ destinations = $('').addClass(config.keyboardDragClass),
+ result = $.when().then(function() {
+ return destinations;
+ }),
createLink = function(parentElement, beforeElement, afterElement) {
if (beforeElement.is(info.element) || afterElement.is(info.element)) {
return;
}
- var li = $('').appendTo(list);
- var a = $('')
- .on('click', function(e) {
- e.preventDefault();
- e.stopPropagation();
- moveElement(parentElement, beforeElement);
- info.endTime = new Date().getTime();
- info.dropped = true;
- info.element.find(config.moveHandlerSelector).focus();
- executeCallback('drop');
- modal.hide();
- })
- .appendTo(li);
- getDestinationName(parentElement, afterElement)
- .then(function(txt) {
- a.text(txt);
- return txt;
- }).catch(Notification.exception);
+ result = result
+ .then(function() {
+ return getDestinationName(parentElement, afterElement);
+ })
+ .then(function(txt) {
+ var li = $('').appendTo(destinations);
+ var a = $('').attr('data-sortable-quickmove', 1).appendTo(li);
+ a.data('parent-element', parentElement).data('before-element', beforeElement).text(txt);
+ return destinations;
+ });
},
addList = function() {
+ // Destination lists may be nested. We want to add all move destinations in the same
+ // order they appear on the screen for the user.
if ($.inArray(this, addedLists) !== -1) {
return;
}
@@ -643,24 +640,37 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
createLink(list, $(), children.last());
};
targets.each(addList);
- return list;
+ return result;
};
/**
* Displays the dialogue to move element.
+ * @param {jQuery} clickedElement element to return focus to after the modal is closed
* @private
*/
- var displayMoveDialogue = function() {
+ var displayMoveDialogue = function(clickedElement) {
ModalFactory.create({
type: ModalFactory.types.CANCEL,
- title: getMoveDialogueTitle(info.element)
+ title: getMoveDialogueTitle(info.element),
+ body: getDestinationsList()
}).then(function(modal) {
+ var quickMoveHandler = function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ moveElement($(e.currentTarget).data('parent-element'), $(e.currentTarget).data('before-element'));
+ info.endTime = new Date().getTime();
+ info.dropped = true;
+ clickedElement.focus();
+ executeCallback('drop');
+ modal.hide();
+ };
+ modal.getRoot().on('click', '[data-sortable-quickmove]', quickMoveHandler);
modal.getRoot().on(ModalEvents.hidden, function() {
// Always destroy when hidden, it is generated dynamically each time.
+ modal.getRoot().off('click', '[data-sortable-quickmove]', quickMoveHandler);
modal.destroy();
finishDragging();
});
- modal.getBody().append(getDestinationsList(modal));
modal.setLarge();
modal.show();
return modal;
@@ -699,17 +709,16 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
* (default 'sortable-list-over-element')
*/
init: function(root, config) {
- if (typeof config === 'undefined' || !config) {
- config = {};
- }
- config = $.extend({}, defaultParameters, CSS, config);
+ config = $.extend({}, defaultParameters, CSS, config || {});
config.listSelector = root;
if (!config.targetListSelector) {
config.targetListSelector = root;
}
if (typeof config.listSelector === 'object') {
+ // The root is an element on the page. Register a listener for this element.
$(config.listSelector).on('mousedown touchstart', {config: config}, dragStartHandler);
} else {
+ // The root is a CSS selector. Register a listener that picks up the element dynamically.
$('body').on('mousedown touchstart', config.listSelector, {config: config}, dragStartHandler);
}
if (config.moveHandlerSelector !== null) {