diff --git a/course/lib.php b/course/lib.php index 84dc89ed48f..2e377a8ae3d 100644 --- a/course/lib.php +++ b/course/lib.php @@ -3241,11 +3241,15 @@ function include_course_ajax($course, $usedmodules = array(), $enabledmodules = 'clicktochangeinbrackets', 'markthistopic', 'markedthistopic', - 'move', 'movesection', + 'movecoursemodule', + 'movecoursesection', 'movecontent', 'tocontent', - 'emptydragdropregion' + 'emptydragdropregion', + 'afterresource', + 'aftersection', + 'totopofsection', ), 'moodle'); // Include section-specific strings for formats which support sections. diff --git a/course/yui/dragdrop/dragdrop.js b/course/yui/dragdrop/dragdrop.js index 7d8a9dd0a68..3269d40d9c9 100644 --- a/course/yui/dragdrop/dragdrop.js +++ b/course/yui/dragdrop/dragdrop.js @@ -278,7 +278,16 @@ YUI.add('moodle-course-dragdrop', function(Y) { this.groups = ['resource']; this.samenodeclass = CSS.ACTIVITY; this.parentnodeclass = CSS.SECTION; - this.resourcedraghandle = this.get_drag_handle(M.str.moodle.move, CSS.EDITINGMOVE, CSS.ICONCLASS, true); + this.resourcedraghandle = this.get_drag_handle(M.util.get_string('movecoursemodule', 'moodle'), CSS.EDITINGMOVE, CSS.ICONCLASS, true); + + this.samenodelabel = { + identifier: 'afterresource', + component: 'moodle' + }; + this.parentnodelabel = { + identifier: 'totopofsection', + component: 'moodle' + }; // Go through all sections var sectionlistselector = M.course.format.get_section_selector(Y); diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 3d4c72b1ec7..1a45a0121d8 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -115,6 +115,8 @@ $string['administratorsandteachers'] = 'Administrators and teachers'; $string['advanced'] = 'Advanced'; $string['advancedfilter'] = 'Advanced search'; $string['advancedsettings'] = 'Advanced settings'; +$string['afterresource'] = 'After resource "{$a}"'; +$string['aftersection'] = 'After section "{$a}"'; $string['again'] = 'again'; $string['aimid'] = 'AIM ID'; $string['ajaxuse'] = 'AJAX and Javascript'; @@ -1157,6 +1159,8 @@ $string['moreinformation'] = 'More information about this error'; $string['moreprofileinfoneeded'] = 'Please tell us more about yourself'; $string['mostrecently'] = 'most recently'; $string['move'] = 'Move'; +$string['movecoursemodule'] = 'Move resource'; +$string['movecoursesection'] = 'Move section'; $string['movecontent'] = 'Move {$a}'; $string['movecategorycontentto'] = 'Move into'; $string['movecategorysuccess'] = 'Successfully moved category \'{$a->moved}\' into category \'{$a->to}\''; @@ -1813,6 +1817,7 @@ $string['topicoutline'] = 'Topic outline'; $string['topicshow'] = 'Show this topic to {$a}'; $string['topichide'] = 'Hide this topic from {$a}'; $string['total'] = 'Total'; +$string['totopofsection'] = 'To the top of section "{$a}"'; $string['trackforums'] = 'Forum tracking'; $string['trackforumsno'] = 'No: don\'t keep track of posts I have seen'; $string['trackforumsyes'] = 'Yes: highlight new posts for me'; diff --git a/lib/yui/dragdrop/dragdrop.js b/lib/yui/dragdrop/dragdrop.js index 773373c2fc6..f6706994d3b 100644 --- a/lib/yui/dragdrop/dragdrop.js +++ b/lib/yui/dragdrop/dragdrop.js @@ -19,6 +19,9 @@ YUI.add('moodle-core-dragdrop', function(Y) { absgoingup : null, samenodeclass : null, parentnodeclass : null, + samenodelabel : null, + parentnodelabel : null, + groups : [], lastdroptarget : null, initializer : function() { @@ -59,7 +62,6 @@ YUI.add('moodle-core-dragdrop', function(Y) { .setAttribute('title', title) .setAttribute('tabIndex', 0) .setAttribute('data-draggroups', this.groups) - .setAttribute('aria-grabbed', 'false') .setAttribute('role', 'button'); dragelement.appendChild(dragicon); dragelement.addClass(MOVEICON.cssclass); @@ -73,6 +75,7 @@ YUI.add('moodle-core-dragdrop', function(Y) { unlock_drag_handle: function(drag, classname) { drag.addHandle('.'+classname); + drag.get('activeHandle').focus(); }, ajax_failure: function(response) { @@ -263,8 +266,6 @@ YUI.add('moodle-core-dragdrop', function(Y) { M.core.dragdrop.keydragcontainer = dragcontainer; M.core.dragdrop.keydraghandle = draghandle; - // Indicate to a screenreader the node that is selected for drag and drop. - dragcontainer.setAttribute('aria-grabbed', 'true'); // Get the name of the thing to move. var nodetitle = this.find_element_text(dragcontainer); var dialogtitle = M.util.get_string('movecontent', 'moodle', nodetitle); @@ -308,13 +309,17 @@ YUI.add('moodle-core-dragdrop', function(Y) { listlink = Y.Node.create(''); nodetitle = this.find_element_text(labelroot); - listitemtext = M.util.get_string('tocontent', 'moodle', nodetitle); + if (this.samenodelabel && node.hasClass(this.samenodeclass)) { + listitemtext = M.util.get_string(this.samenodelabel.identifier, this.samenodelabel.component, nodetitle); + } else if (this.parentnodelabel && node.hasClass(this.parentnodeclass)) { + listitemtext = M.util.get_string(this.parentnodelabel.identifier, this.parentnodelabel.component, nodetitle); + } else { + listitemtext = M.util.get_string('tocontent', 'moodle', nodetitle); + } listlink.setContent(listitemtext); // Add a data attribute so we can get the real drop target. listlink.setAttribute('data-drop-target', node.get('id')); - // Notify the screen reader this is a valid drop target. - listlink.setAttribute('aria-dropeffect', 'move'); // Allow tabbing to the link. listlink.setAttribute('tabindex', '0'); @@ -337,6 +342,14 @@ YUI.add('moodle-core-dragdrop', function(Y) { centered : true }); + M.core.dragdrop.dropui.after('visibleChange', function(e) { + // After the dialogue has been closed, we call the cancel function. This will + // ensure that tidying up happens (e.g. focusing on the start Node). + if (e.prevVal && !e.newVal) { + this.global_cancel_keyboard_drag(); + } + }, this); + // Focus the first drop target. if (droplist.one('a')) { droplist.one('a').focus(); @@ -376,6 +389,9 @@ YUI.add('moodle-core-dragdrop', function(Y) { if (param == 'node' || param == 'dragNode' || param == 'dropNode') { return this.node; } + if (param === 'activeHandle') { + return this.node.one('.editing_move'); + } return null; }; @@ -404,7 +420,6 @@ YUI.add('moodle-core-dragdrop', function(Y) { global_keyboard_drop : function(e) { // The drag node was saved. var dragcontainer = M.core.dragdrop.keydragcontainer; - dragcontainer.setAttribute('aria-grabbed', 'false'); // The real drop node is stored in an attribute of the proxy. var droptarget = Y.one('#' + e.target.getAttribute('data-drop-target')); @@ -419,7 +434,6 @@ YUI.add('moodle-core-dragdrop', function(Y) { this.drag_start(dragevent); this.global_drop_over(dropevent); this.global_drop_hit(dropevent); - M.core.dragdrop.keydraghandle.focus(); }, /** @@ -429,7 +443,7 @@ YUI.add('moodle-core-dragdrop', function(Y) { */ global_cancel_keyboard_drag : function() { if (M.core.dragdrop.keydragcontainer) { - M.core.dragdrop.keydragcontainer.setAttribute('aria-grabbed', 'false'); + // Focus on the node which was being dragged. M.core.dragdrop.keydraghandle.focus(); M.core.dragdrop.keydragcontainer = null; }