diff --git a/lib/amd/build/sortable_list.min.js b/lib/amd/build/sortable_list.min.js
index 5b46286d6ce..f3247eaf9af 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={targetListSelector:null,moveHandlerSelector:null,isHorizontal:!1,autoScroll:!0},i={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"};a.event.special.touchstart={setup:function(a,b,c){return!!b.includes("notPassive")&&(this.addEventListener("touchstart",c,{passive:!1}),!0)}};var j=function(b,c){this.info=null,this.proxy=null,this.proxyDelta=null,this.dragCounter=0,this.lastEvent=null,this.config=a.extend({},h,c||{}),this.config.listSelector=b,this.config.targetListSelector||(this.config.targetListSelector=b),"object"==typeof this.config.listSelector?a(this.config.listSelector).on("mousedown touchstart.notPassive",a.proxy(this.dragStartHandler,this)):a("body").on("mousedown touchstart.notPassive",this.config.listSelector,a.proxy(this.dragStartHandler,this)),null!==this.config.moveHandlerSelector&&a("body").on("click keypress",this.config.moveHandlerSelector,a.proxy(this.clickHandler,this))};return j.EVENTS={DRAGSTART:"sortablelist-dragstart",DRAG:"sortablelist-drag",DROP:"sortablelist-drop",DRAGEND:"sortablelist-dragend"},j.prototype.resetDraggedClasses=function(){var b=[i.isDraggedClass,i.currentPositionClass,i.overElementClass,i.targetListClass];for(var c in b)a("."+b[c]).removeClass(b[c]);this.proxy&&(this.proxy.remove(),this.proxy=a())},j.prototype.calculatePositionOnPage=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=this.lastEvent.pageX,b.pageY=this.lastEvent.pageY):this.lastEvent=b,void 0===b.clientX&&(b.clientX=Math.round(b.pageX-a(window).scrollLeft()),b.clientY=Math.round(b.pageY-a(window).scrollTop()))},j.prototype.dragStartHandler=function(b){if(null!==this.info){if("click"===this.info.type||"touchend"===this.info.type)return;this.moveElement(this.info.sourceList,this.info.sourceNextElement),this.finishDragging()}if("mousedown"!==b.type||1===b.which){this.calculatePositionOnPage(b);var d=a(b.target).closest(a(b.currentTarget).children());if(d.length&&(null===this.config.moveHandlerSelector||a(b.target).closest(this.config.moveHandlerSelector,d).length)){b.stopPropagation(),b.preventDefault(),this.dragCounter++,this.info={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(this.config.targetListSelector).addClass(i.targetListClass);var e=d.offset();d.addClass(i.currentPositionClass),this.proxyDelta={x:e.left-b.pageX,y:e.top-b.pageY},this.proxy=a();var f=this.dragCounter;setTimeout(a.proxy(function(){null!==this.info&&"click"!==this.info.type&&"keypress"!==this.info.type&&this.dragCounter===f&&this.createProxy()},this),500),a(window).on("mousemove touchmove mouseup touchend",a.proxy(this.dragHandler,this)),a(window).on("keypress",a.proxy(this.dragcancelHandler,this)),this.config.autoScroll&&c.start(function(){a(window).trigger("mousemove")}),this.executeCallback(j.EVENTS.DRAGSTART)}}},j.prototype.createProxy=function(){this.proxy=this.info.element.clone(),this.info.sourceList.append(this.proxy),this.proxy.removeAttr("id").removeClass(i.currentPositionClass).addClass(i.isDraggedClass).css({position:"fixed"}),this.proxy.offset({top:this.proxyDelta.y+this.lastEvent.pageY,left:this.proxyDelta.x+this.lastEvent.pageX})},j.prototype.clickHandler=function(b){if(!("keypress"===b.type&&13!==b.originalEvent.keyCode&&32!==b.originalEvent.keyCode||null!==this.info&&"click"===this.info.type)){b.preventDefault(),b.stopPropagation();var c=a(b.target).closest(this.config.moveHandlerSelector),d=c.closest(this.config.listSelector),e=c.closest(d.children());e.length&&(this.dragCounter++,this.info={element:e,sourceNextElement:e.next(),sourceList:d,targetNextElement:e.next(),targetList:d,dropped:!1,type:b.type,startTime:(new Date).getTime()},this.executeCallback(j.EVENTS.DRAGSTART),this.displayMoveDialogue(c))}},j.prototype.getPositionInNode=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},j.prototype.isListHorizontal=function(a){var b=this.config.isHorizontal;return b===!0||b===!1?b:b(a)},j.prototype.dragHandler=function(b){this.calculatePositionOnPage(b),this.proxy.offset({top:-1e3,left:-1e3});var c=a(document.elementFromPoint(b.clientX,b.clientY)),d=this.info.element[0],e=function(){return this!==d},f=c.closest("."+i.targetListClass+" > :not(."+i.isDraggedClass+")").filter(e),g=c.closest("."+i.targetListClass),h=this.proxy,k=function(){return!h||!h.length||this!==h[0]};if(a("."+i.overElementClass).removeClass(i.overElementClass),f.addClass(i.overElementClass),this.proxy.offset({top:this.proxyDelta.y+b.pageY,left:this.proxyDelta.x+b.pageX}),g.length&&!g.children().filter(k).length)this.moveElement(g,a());else if(1===f.length&&!this.info.element.find(f[0]).length){var l=this.getPositionInNode(b.pageX,b.pageY,f);if(l){var m=f.parent(),n=this.isListHorizontal(m)?l.xRatio:l.yRatio,o=f.find("."+i.targetListClass),p=!o.children().filter(k).filter(e).length;o.length&&p&&n>.2&&n<.8?this.moveElement(o,a()):n>.5?this.moveElement(m,f.next().filter(k)):this.moveElement(m,f)}}if("mouseup"===b.type||"touchend"===b.type){this.info.endX=b.pageX,this.info.endY=b.pageY,this.info.endTime=(new Date).getTime(),this.info.dropped=!0,this.info.positionChanged=this.hasPositionChanged(this.info);var q=this.info;this.executeCallback(j.EVENTS.DROP),this.finishDragging(),"touchend"===b.type&&null!==this.config.moveHandlerSelector&&q.endTime-q.startTime<500&&!q.positionChanged&&this.clickHandler(b)}},j.prototype.hasPositionChanged=function(a){return a.sourceList[0]!==a.targetList[0]||a.sourceNextElement.length!==a.targetNextElement.length||a.sourceNextElement.length&&a.sourceNextElement[0]!==a.targetNextElement[0]},j.prototype.moveElement=function(a,b){var c=this.info.element;b.length&&b[0]===c[0]||a[0]===this.info.targetList[0]&&b.length===this.info.targetNextElement.length&&b[0]===this.info.targetNextElement[0]||(b.length?a[0].insertBefore(c[0],b[0]):this.proxy&&this.proxy.parent().length&&this.proxy.parent()[0]===a[0]?a[0].insertBefore(c[0],this.proxy[0]):a[0].appendChild(c[0]),this.info.targetList=a,this.info.targetNextElement=b,this.executeCallback(j.EVENTS.DRAG))},j.prototype.finishDragging=function(){this.resetDraggedClasses(),this.config.autoScroll&&c.stop(),a(window).off("mousemove touchmove mouseup touchend",a.proxy(this.dragHandler,this)),a(window).off("keypress",a.proxy(this.dragcancelHandler,this)),this.executeCallback(j.EVENTS.DRAGEND),this.info=null},j.prototype.executeCallback=function(a){this.info.element.trigger(a,this.info)},j.prototype.dragcancelHandler=function(a){"keypress"===a.type&&27===a.originalEvent.keyCode&&(this.moveElement(this.info.sourceList,this.info.sourceNextElement),this.finishDragging())},j.prototype.getElementName=function(b){return a.Deferred().resolve(b.text())},j.prototype.getDestinationName=function(a,b){return b.length?this.getElementName(b).then(function(a){return d.get_string("movecontentafter","moodle",a)}):d.get_string("movecontenttothetop","moodle")},j.prototype.getMoveDialogueTitle=function(a){return this.getElementName(a).then(function(a){return d.get_string("movecontent","moodle",a)})},j.prototype.getDestinationsList=function(){var b=[],c=a(this.config.targetListSelector),d=a("
").addClass(i.keyboardDragClass),e=a.when().then(function(){return d}),f=a.proxy(function(b,c,f){c.is(this.info.element)||f.is(this.info.element)||a.contains(this.info.element[0],b[0])||(e=e.then(a.proxy(function(){return this.getDestinationName(b,f)},this)).then(function(e){var f=a("").appendTo(d),g=a('').attr("data-core_sortable_list-quickmove",1).appendTo(f);return g.data("parent-element",b).data("before-element",c).text(e),d}))},this),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},j.prototype.displayMoveDialogue=function(b){e.create({type:e.types.CANCEL,title:this.getMoveDialogueTitle(this.info.element),body:this.getDestinationsList()}).then(a.proxy(function(c){var d=a.proxy(function(d){d.preventDefault(),d.stopPropagation(),this.moveElement(a(d.currentTarget).data("parent-element"),a(d.currentTarget).data("before-element")),this.info.endTime=(new Date).getTime(),this.info.positionChanged=this.hasPositionChanged(this.info),this.info.dropped=!0,b.focus(),this.executeCallback(j.EVENTS.DROP),c.hide()},this);return c.getRoot().on("click","[data-core_sortable_list-quickmove]",d),c.getRoot().on(f.hidden,a.proxy(function(){c.getRoot().off("click","[data-core_sortable_list-quickmove]",d),c.destroy(),this.finishDragging()},this)),c.setLarge(),c.show(),c},this))["catch"](g.exception)},j});
\ 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={targetListSelector:null,moveHandlerSelector:"[data-drag-type=move]",isHorizontal:!1,autoScroll:!0},i={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"},j=function(){var a,b=!1,c="testpassiveeventoptions";try{a=Object.defineProperty({},"passive",{get:function(){b=!0}}),document.addEventListener(c,a,a),document.removeEventListener(c,a,a)}catch(d){b=!1}return b}();a.event.special.touchstart={setup:function(a,b,c){return!(!j||!b.includes("notPassive"))&&(this.addEventListener("touchstart",c,{passive:!1}),!0)}};var k=function(b,c){this.info=null,this.proxy=null,this.proxyDelta=null,this.dragCounter=0,this.lastEvent=null,this.config=a.extend({},h,c||{}),this.config.listSelector=b,this.config.targetListSelector||(this.config.targetListSelector=b),"object"==typeof this.config.listSelector?a(this.config.listSelector).on("mousedown touchstart.notPassive",a.proxy(this.dragStartHandler,this)):a("body").on("mousedown touchstart.notPassive",this.config.listSelector,a.proxy(this.dragStartHandler,this)),null!==this.config.moveHandlerSelector&&a("body").on("click keypress",this.config.moveHandlerSelector,a.proxy(this.clickHandler,this))};return k.EVENTS={DRAGSTART:"sortablelist-dragstart",DRAG:"sortablelist-drag",DROP:"sortablelist-drop",DRAGEND:"sortablelist-dragend"},k.prototype.resetDraggedClasses=function(){var b=[i.isDraggedClass,i.currentPositionClass,i.overElementClass,i.targetListClass];for(var c in b)a("."+b[c]).removeClass(b[c]);this.proxy&&(this.proxy.remove(),this.proxy=a())},k.prototype.calculatePositionOnPage=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=this.lastEvent.pageX,b.pageY=this.lastEvent.pageY):this.lastEvent=b,void 0===b.clientX&&(b.clientX=Math.round(b.pageX-a(window).scrollLeft()),b.clientY=Math.round(b.pageY-a(window).scrollTop()))},k.prototype.dragStartHandler=function(b){if(null!==this.info){if("click"===this.info.type||"touchend"===this.info.type)return;this.moveElement(this.info.sourceList,this.info.sourceNextElement),this.finishDragging()}if("mousedown"!==b.type||1===b.which){this.calculatePositionOnPage(b);var d=a(b.target).closest(a(b.currentTarget).children());if(d.length&&(null===this.config.moveHandlerSelector||a(b.target).closest(this.config.moveHandlerSelector,d).length)){b.stopPropagation(),b.preventDefault(),this.dragCounter++,this.info={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(this.config.targetListSelector).addClass(i.targetListClass);var e=d.offset();d.addClass(i.currentPositionClass),this.proxyDelta={x:e.left-b.pageX,y:e.top-b.pageY},this.proxy=a();var f=this.dragCounter;setTimeout(a.proxy(function(){null!==this.info&&"click"!==this.info.type&&"keypress"!==this.info.type&&this.dragCounter===f&&this.createProxy()},this),500),a(window).on("mousemove touchmove mouseup touchend",a.proxy(this.dragHandler,this)),a(window).on("keypress",a.proxy(this.dragcancelHandler,this)),this.config.autoScroll&&c.start(function(){a(window).trigger("mousemove")}),this.executeCallback(k.EVENTS.DRAGSTART)}}},k.prototype.createProxy=function(){this.proxy=this.info.element.clone(),this.info.sourceList.append(this.proxy),this.proxy.removeAttr("id").removeClass(i.currentPositionClass).addClass(i.isDraggedClass).css({position:"fixed"}),this.proxy.offset({top:this.proxyDelta.y+this.lastEvent.pageY,left:this.proxyDelta.x+this.lastEvent.pageX})},k.prototype.clickHandler=function(b){if(!("keypress"===b.type&&13!==b.originalEvent.keyCode&&32!==b.originalEvent.keyCode||null!==this.info&&"click"===this.info.type)){b.preventDefault(),b.stopPropagation();var c=a(b.target).closest(this.config.moveHandlerSelector),d=c.closest(this.config.listSelector),e=c.closest(d.children());e.length&&(this.dragCounter++,this.info={element:e,sourceNextElement:e.next(),sourceList:d,targetNextElement:e.next(),targetList:d,dropped:!1,type:b.type,startTime:(new Date).getTime()},this.executeCallback(k.EVENTS.DRAGSTART),this.displayMoveDialogue(c))}},k.prototype.getPositionInNode=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},k.prototype.isListHorizontal=function(a){var b=this.config.isHorizontal;return b===!0||b===!1?b:b(a)},k.prototype.dragHandler=function(b){this.calculatePositionOnPage(b),this.proxy.offset({top:-1e3,left:-1e3});var c=a(document.elementFromPoint(b.clientX,b.clientY)),d=this.info.element[0],e=function(){return this!==d},f=c.closest("."+i.targetListClass+" > :not(."+i.isDraggedClass+")").filter(e),g=c.closest("."+i.targetListClass),h=this.proxy,j=function(){return!h||!h.length||this!==h[0]};if(a("."+i.overElementClass).removeClass(i.overElementClass),f.addClass(i.overElementClass),this.proxy.offset({top:this.proxyDelta.y+b.pageY,left:this.proxyDelta.x+b.pageX}),g.length&&!g.children().filter(j).length)this.moveElement(g,a());else if(1===f.length&&!this.info.element.find(f[0]).length){var l=this.getPositionInNode(b.pageX,b.pageY,f);if(l){var m=f.parent(),n=this.isListHorizontal(m)?l.xRatio:l.yRatio,o=f.find("."+i.targetListClass),p=!o.children().filter(j).filter(e).length;o.length&&p&&n>.2&&n<.8?this.moveElement(o,a()):n>.5?this.moveElement(m,f.next().filter(j)):this.moveElement(m,f)}}if("mouseup"===b.type||"touchend"===b.type){this.info.endX=b.pageX,this.info.endY=b.pageY,this.info.endTime=(new Date).getTime(),this.info.dropped=!0,this.info.positionChanged=this.hasPositionChanged(this.info);var q=this.info;this.executeCallback(k.EVENTS.DROP),this.finishDragging(),"touchend"===b.type&&null!==this.config.moveHandlerSelector&&q.endTime-q.startTime<500&&!q.positionChanged&&this.clickHandler(b)}},k.prototype.hasPositionChanged=function(a){return a.sourceList[0]!==a.targetList[0]||a.sourceNextElement.length!==a.targetNextElement.length||a.sourceNextElement.length&&a.sourceNextElement[0]!==a.targetNextElement[0]},k.prototype.moveElement=function(a,b){var c=this.info.element;b.length&&b[0]===c[0]||a[0]===this.info.targetList[0]&&b.length===this.info.targetNextElement.length&&b[0]===this.info.targetNextElement[0]||(b.length?a[0].insertBefore(c[0],b[0]):this.proxy&&this.proxy.parent().length&&this.proxy.parent()[0]===a[0]?a[0].insertBefore(c[0],this.proxy[0]):a[0].appendChild(c[0]),this.info.targetList=a,this.info.targetNextElement=b,this.executeCallback(k.EVENTS.DRAG))},k.prototype.finishDragging=function(){this.resetDraggedClasses(),this.config.autoScroll&&c.stop(),a(window).off("mousemove touchmove mouseup touchend",a.proxy(this.dragHandler,this)),a(window).off("keypress",a.proxy(this.dragcancelHandler,this)),this.executeCallback(k.EVENTS.DRAGEND),this.info=null},k.prototype.executeCallback=function(a){this.info.element.trigger(a,this.info)},k.prototype.dragcancelHandler=function(a){"keypress"===a.type&&27===a.originalEvent.keyCode&&(this.moveElement(this.info.sourceList,this.info.sourceNextElement),this.finishDragging())},k.prototype.getElementName=function(b){return a.Deferred().resolve(b.text())},k.prototype.getDestinationName=function(a,b){return b.length?this.getElementName(b).then(function(a){return d.get_string("movecontentafter","moodle",a)}):d.get_string("movecontenttothetop","moodle")},k.prototype.getMoveDialogueTitle=function(b,c){return c.attr("title")?a.Deferred().resolve(c.attr("title")):this.getElementName(b).then(function(a){return d.get_string("movecontent","moodle",a)})},k.prototype.getDestinationsList=function(){var b=[],c=a(this.config.targetListSelector),d=a("").addClass(i.keyboardDragClass),e=a.when().then(function(){return d}),f=a.proxy(function(b,c,f){c.is(this.info.element)||f.is(this.info.element)||a.contains(this.info.element[0],b[0])||(e=e.then(a.proxy(function(){return this.getDestinationName(b,f)},this)).then(function(e){var f=a("").appendTo(d),g=a('').attr("data-core_sortable_list-quickmove",1).appendTo(f);return g.data("parent-element",b).data("before-element",c).text(e),d}))},this),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},k.prototype.displayMoveDialogue=function(b){e.create({type:e.types.CANCEL,title:this.getMoveDialogueTitle(this.info.element,b),body:this.getDestinationsList()}).then(a.proxy(function(c){var d=a.proxy(function(d){d.preventDefault(),d.stopPropagation(),this.moveElement(a(d.currentTarget).data("parent-element"),a(d.currentTarget).data("before-element")),this.info.endTime=(new Date).getTime(),this.info.positionChanged=this.hasPositionChanged(this.info),this.info.dropped=!0,b.focus(),this.executeCallback(k.EVENTS.DROP),c.hide()},this);return c.getRoot().on("click","[data-core_sortable_list-quickmove]",d),c.getRoot().on(f.hidden,a.proxy(function(){c.getRoot().off("click","[data-core_sortable_list-quickmove]",d),c.destroy(),this.finishDragging()},this)),c.setLarge(),c.show(),c},this))["catch"](g.exception)},k});
\ No newline at end of file
diff --git a/lib/amd/src/sortable_list.js b/lib/amd/src/sortable_list.js
index 44fa887d555..4606d439df2 100644
--- a/lib/amd/src/sortable_list.js
+++ b/lib/amd/src/sortable_list.js
@@ -18,12 +18,16 @@
*
* Example of usage:
*
+ * Create a list (for example or ) where each draggable element has a drag handle.
+ * The best practice is to use the template core/drag_handle:
+ * $OUTPUT->render_from_template('core/drag_handle', ['movetitle' => get_string('movecontent', 'moodle', ELEMENTNAME)]);
+ *
+ * Attach this JS module to this list:
+ *
* define(['jquery', 'core/sortable_list'], function($, SortableList) {
- * var list = new SortableList('ul.my-awesome-list', // source list (usually or ) - selector or element
- * {
- * moveHandlerSelector: '.draghandle' // CSS selector of the crossarrow handle. Make sure that this
- * // element can handle keypress and mouse click events for displaying accessible move popup.
- * });
+ * var list = new SortableList('ul.my-awesome-list'); // source list (usually or ) - selector or element
+ *
+ * // Listen to the events when element is dragged.
* $('ul.my-awesome-list > *').on(SortableList.EVENTS.DROP, function(evt, info) {
* console.log(info);
* });
@@ -62,7 +66,7 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
*/
var defaultParameters = {
targetListSelector: null,
- moveHandlerSelector: null,
+ moveHandlerSelector: '[data-drag-type=move]',
isHorizontal: false,
autoScroll: true
};
@@ -82,6 +86,36 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
overElementClass: 'sortable-list-over-element'
};
+ /**
+ * Test the browser support for options objects on event listeners.
+ * @return Boolean
+ */
+ var eventListenerOptionsSupported = (function() {
+ var passivesupported = false,
+ options,
+ testeventname = "testpassiveeventoptions";
+
+ // Options support testing example from:
+ // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
+
+ try {
+ options = Object.defineProperty({}, "passive", {
+ get: function() {
+ passivesupported = true;
+ }
+ });
+
+ // We use an event name that is not likely to conflict with any real event.
+ document.addEventListener(testeventname, options, options);
+ // We remove the event listener as we have tested the options already.
+ document.removeEventListener(testeventname, options, options);
+ } catch (err) {
+ // It's already false.
+ passivesupported = false;
+ }
+ return passivesupported;
+ })();
+
/**
* Allow to create non-passive touchstart listeners and prevent page scrolling when dragging
* From: https://stackoverflow.com/a/48098097
@@ -90,7 +124,7 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
*/
$.event.special.touchstart = {
setup: function(_, ns, handle) {
- if (ns.includes('notPassive')) {
+ if (eventListenerOptionsSupported && ns.includes('notPassive')) {
this.addEventListener('touchstart', handle, {passive: false});
return true;
} else {
@@ -105,8 +139,7 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
* @param {(String|jQuery|Element)} root JQuery/DOM element representing sortable list (i.e. , ) or CSS selector
* @param {Object} config Parameters for the list. See defaultParameters above for examples.
* @property {(String|jQuery|Element)} config.targetListSelector target lists, by default same as root
- * @property {String} config.moveHandlerSelector CSS selector for a drag handle. By default the whole item is a handle.
- * Without drag handle sorting is not accessible!
+ * @property {String} config.moveHandlerSelector CSS selector for a drag handle. By default '[data-drag-type=move]'
* @property {String} config.targetListSelector CSS selector for target lists. By default the same as root
* @property {(Boolean|Function)} config.isHorizontal Set to true if the list is horizontal
* (can also be a callback with list as an argument)
@@ -607,9 +640,13 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
*
* @public
* @param {jQuery} element
+ * @param {jQuery} handler
* @return {Promise}
*/
- SortableList.prototype.getMoveDialogueTitle = function(element) {
+ SortableList.prototype.getMoveDialogueTitle = function(element, handler) {
+ if (handler.attr('title')) {
+ return $.Deferred().resolve(handler.attr('title'));
+ }
return this.getElementName(element).then(function(name) {
return str.get_string('movecontent', 'moodle', name);
});
@@ -677,7 +714,7 @@ function($, log, autoScroll, str, ModalFactory, ModalEvents, Notification) {
SortableList.prototype.displayMoveDialogue = function(clickedElement) {
ModalFactory.create({
type: ModalFactory.types.CANCEL,
- title: this.getMoveDialogueTitle(this.info.element),
+ title: this.getMoveDialogueTitle(this.info.element, clickedElement),
body: this.getDestinationsList()
}).then($.proxy(function(modal) {
var quickMoveHandler = $.proxy(function(e) {
diff --git a/lib/templates/drag_handle.mustache b/lib/templates/drag_handle.mustache
new file mode 100644
index 00000000000..4432bbb15b1
--- /dev/null
+++ b/lib/templates/drag_handle.mustache
@@ -0,0 +1,27 @@
+{{!
+ 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 .
+}}
+{{!
+ @template core/drag_handle
+
+ Drag handle template.
+
+ Example context (json):
+ {
+ "movetitle": "Move this element"
+ }
+}}
+{{#pix}} i/dragdrop, core {{/pix}}
diff --git a/theme/boost/scss/moodle/core.scss b/theme/boost/scss/moodle/core.scss
index 52b02fb4f9b..b22908e144d 100644
--- a/theme/boost/scss/moodle/core.scss
+++ b/theme/boost/scss/moodle/core.scss
@@ -2070,6 +2070,7 @@ $footer-link-color: $bg-inverse-link-color !default;
[data-drag-type="move"] {
cursor: move;
+ touch-action: none;
}
.clickable {
diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css
index b0f897b2d17..b430c6ea3cb 100644
--- a/theme/boost/style/moodle.css
+++ b/theme/boost/style/moodle.css
@@ -10386,7 +10386,8 @@ ul {
top: 0; }
[data-drag-type="move"] {
- cursor: move; }
+ cursor: move;
+ touch-action: none; }
.clickable {
cursor: pointer; }
diff --git a/theme/bootstrapbase/less/moodle/core.less b/theme/bootstrapbase/less/moodle/core.less
index 6631c22b7ba..251435cb49d 100644
--- a/theme/bootstrapbase/less/moodle/core.less
+++ b/theme/bootstrapbase/less/moodle/core.less
@@ -2425,6 +2425,7 @@ h3.sectionname .inplaceeditable.inplaceeditingon .editinstructions {
[data-drag-type="move"] {
cursor: move;
+ touch-action: none;
}
.bg-pulse-grey {
diff --git a/theme/bootstrapbase/style/moodle.css b/theme/bootstrapbase/style/moodle.css
index e047b70e8f8..79dd22b5076 100644
--- a/theme/bootstrapbase/style/moodle.css
+++ b/theme/bootstrapbase/style/moodle.css
@@ -4807,6 +4807,7 @@ h3.sectionname .inplaceeditable.inplaceeditingon .editinstructions {
}
[data-drag-type="move"] {
cursor: move;
+ touch-action: none;
}
.bg-pulse-grey {
animation: bg-pulse-grey 2s infinite linear;