| 1 | efrain | 1 | /**
 | 
        
           |  |  | 2 |  * Drag and Drop handler
 | 
        
           |  |  | 3 |  *
 | 
        
           |  |  | 4 |  * @namespace M.course.management
 | 
        
           |  |  | 5 |  * @class DragDrop
 | 
        
           |  |  | 6 |  * @constructor
 | 
        
           |  |  | 7 |  * @extends Base
 | 
        
           |  |  | 8 |  */
 | 
        
           |  |  | 9 | DragDrop = function(config) {
 | 
        
           |  |  | 10 |     Console.superclass.constructor.apply(this, [config]);
 | 
        
           |  |  | 11 | };
 | 
        
           |  |  | 12 | DragDrop.NAME = 'moodle-course-management-dd';
 | 
        
           |  |  | 13 | DragDrop.CSS_PREFIX = 'management-dd';
 | 
        
           |  |  | 14 | DragDrop.ATTRS = {
 | 
        
           |  |  | 15 |     /**
 | 
        
           |  |  | 16 |      * The management console this drag and drop has been set up for.
 | 
        
           |  |  | 17 |      * @attribute console
 | 
        
           |  |  | 18 |      * @type Console
 | 
        
           |  |  | 19 |      * @writeOnce
 | 
        
           |  |  | 20 |      */
 | 
        
           |  |  | 21 |     console: {
 | 
        
           |  |  | 22 |         writeOnce: 'initOnly'
 | 
        
           |  |  | 23 |     }
 | 
        
           |  |  | 24 | };
 | 
        
           |  |  | 25 | DragDrop.prototype = {
 | 
        
           |  |  | 26 |     /**
 | 
        
           |  |  | 27 |      * True if the user is dragging a course upwards.
 | 
        
           |  |  | 28 |      * @property goingup
 | 
        
           |  |  | 29 |      * @protected
 | 
        
           |  |  | 30 |      * @default false
 | 
        
           |  |  | 31 |      */
 | 
        
           |  |  | 32 |     goingup: false,
 | 
        
           |  |  | 33 |   | 
        
           |  |  | 34 |     /**
 | 
        
           |  |  | 35 |      * The last Y position of the course being dragged
 | 
        
           |  |  | 36 |      * @property lasty
 | 
        
           |  |  | 37 |      * @protected
 | 
        
           |  |  | 38 |      * @default null
 | 
        
           |  |  | 39 |      */
 | 
        
           |  |  | 40 |     lasty: null,
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 |     /**
 | 
        
           |  |  | 43 |      * The sibling above the course being dragged currently (tracking its original position).
 | 
        
           |  |  | 44 |      *
 | 
        
           |  |  | 45 |      * @property previoussibling
 | 
        
           |  |  | 46 |      * @protected
 | 
        
           |  |  | 47 |      * @default false
 | 
        
           |  |  | 48 |      */
 | 
        
           |  |  | 49 |     previoussibling: null,
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 |     /**
 | 
        
           |  |  | 52 |      * Initialises the DragDrop instance.
 | 
        
           |  |  | 53 |      * @method initializer
 | 
        
           |  |  | 54 |      */
 | 
        
           |  |  | 55 |     initializer: function() {
 | 
        
           |  |  | 56 |         var managementconsole = this.get('console'),
 | 
        
           |  |  | 57 |             container = managementconsole.get('element'),
 | 
        
           |  |  | 58 |             categorylisting = container.one('#category-listing'),
 | 
        
           |  |  | 59 |             courselisting = container.one('#course-listing > .course-listing'),
 | 
        
           | 1441 | ariadna | 60 |             categoryul = (categorylisting) ? categorylisting.one('ul.category-list') : null,
 | 
        
           |  |  | 61 |             courseul = (courselisting) ? courselisting.one('ul.course-list') : null,
 | 
        
           | 1 | efrain | 62 |             canmoveoutof = (courselisting) ? courselisting.getData('canmoveoutof') : false,
 | 
        
           |  |  | 63 |             contstraint = (canmoveoutof) ? container : courseul;
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 |         if (!courseul) {
 | 
        
           |  |  | 66 |             // No course listings found.
 | 
        
           |  |  | 67 |             return false;
 | 
        
           |  |  | 68 |         }
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 |         while (contstraint.get('scrollHeight') === 0 && !contstraint.compareTo(window.document.body)) {
 | 
        
           |  |  | 71 |             contstraint = contstraint.get('parentNode');
 | 
        
           |  |  | 72 |         }
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |         courseul.all('> li').each(function(li) {
 | 
        
           |  |  | 75 |             this.initCourseListing(li, contstraint);
 | 
        
           |  |  | 76 |         }, this);
 | 
        
           |  |  | 77 |         courseul.setData('dd', new Y.DD.Drop({
 | 
        
           |  |  | 78 |             node: courseul
 | 
        
           |  |  | 79 |         }));
 | 
        
           |  |  | 80 |         if (canmoveoutof && categoryul) {
 | 
        
           |  |  | 81 |             // Category UL may not be there if viewmode is just courses.
 | 
        
           |  |  | 82 |             categoryul.all('li > div').each(function(div) {
 | 
        
           |  |  | 83 |                 this.initCategoryListitem(div);
 | 
        
           |  |  | 84 |             }, this);
 | 
        
           |  |  | 85 |         }
 | 
        
           |  |  | 86 |         Y.DD.DDM.on('drag:start', this.dragStart, this);
 | 
        
           |  |  | 87 |         Y.DD.DDM.on('drag:end', this.dragEnd, this);
 | 
        
           |  |  | 88 |         Y.DD.DDM.on('drag:drag', this.dragDrag, this);
 | 
        
           |  |  | 89 |         Y.DD.DDM.on('drop:over', this.dropOver, this);
 | 
        
           |  |  | 90 |         Y.DD.DDM.on('drop:enter', this.dropEnter, this);
 | 
        
           |  |  | 91 |         Y.DD.DDM.on('drop:exit', this.dropExit, this);
 | 
        
           |  |  | 92 |         Y.DD.DDM.on('drop:hit', this.dropHit, this);
 | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 |     },
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |     /**
 | 
        
           |  |  | 97 |      * Initialises a course listing.
 | 
        
           |  |  | 98 |      * @method initCourseListing
 | 
        
           |  |  | 99 |      * @param Node
 | 
        
           |  |  | 100 |      */
 | 
        
           |  |  | 101 |     initCourseListing: function(node, contstraint) {
 | 
        
           |  |  | 102 |         node.setData('dd', new Y.DD.Drag({
 | 
        
           |  |  | 103 |             node: node,
 | 
        
           |  |  | 104 |             target: {
 | 
        
           |  |  | 105 |                 padding: '0 0 0 20'
 | 
        
           |  |  | 106 |             }
 | 
        
           |  |  | 107 |         }).addHandle(
 | 
        
           |  |  | 108 |             '.drag-handle'
 | 
        
           |  |  | 109 |         ).plug(Y.Plugin.DDProxy, {
 | 
        
           |  |  | 110 |             moveOnEnd: false,
 | 
        
           |  |  | 111 |             borderStyle: false
 | 
        
           |  |  | 112 |         }).plug(Y.Plugin.DDConstrained, {
 | 
        
           |  |  | 113 |             constrain2node: contstraint
 | 
        
           |  |  | 114 |         }));
 | 
        
           |  |  | 115 |     },
 | 
        
           |  |  | 116 |   | 
        
           |  |  | 117 |     /**
 | 
        
           |  |  | 118 |      * Initialises a category listing.
 | 
        
           |  |  | 119 |      * @method initCategoryListitem
 | 
        
           |  |  | 120 |      * @param Node
 | 
        
           |  |  | 121 |      */
 | 
        
           |  |  | 122 |     initCategoryListitem: function(node) {
 | 
        
           |  |  | 123 |         node.setData('dd', new Y.DD.Drop({
 | 
        
           |  |  | 124 |             node: node
 | 
        
           |  |  | 125 |         }));
 | 
        
           |  |  | 126 |     },
 | 
        
           |  |  | 127 |   | 
        
           |  |  | 128 |     /**
 | 
        
           |  |  | 129 |      * Dragging has started.
 | 
        
           |  |  | 130 |      * @method dragStart
 | 
        
           |  |  | 131 |      * @private
 | 
        
           |  |  | 132 |      * @param {EventFacade} e
 | 
        
           |  |  | 133 |      */
 | 
        
           |  |  | 134 |     dragStart: function(e) {
 | 
        
           |  |  | 135 |         var drag = e.target,
 | 
        
           |  |  | 136 |             node = drag.get('node'),
 | 
        
           |  |  | 137 |             dragnode = drag.get('dragNode');
 | 
        
           |  |  | 138 |         node.addClass('course-being-dragged');
 | 
        
           |  |  | 139 |         dragnode.addClass('course-being-dragged-proxy').set('innerHTML', node.one('a.coursename').get('innerHTML'));
 | 
        
           |  |  | 140 |         this.previoussibling = node.get('previousSibling');
 | 
        
           |  |  | 141 |     },
 | 
        
           |  |  | 142 |   | 
        
           |  |  | 143 |     /**
 | 
        
           |  |  | 144 |      * Dragging has ended.
 | 
        
           |  |  | 145 |      * @method dragEnd
 | 
        
           |  |  | 146 |      * @private
 | 
        
           |  |  | 147 |      * @param {EventFacade} e
 | 
        
           |  |  | 148 |      */
 | 
        
           |  |  | 149 |     dragEnd: function(e) {
 | 
        
           |  |  | 150 |         var drag = e.target,
 | 
        
           |  |  | 151 |             node = drag.get('node');
 | 
        
           |  |  | 152 |         node.removeClass('course-being-dragged');
 | 
        
           |  |  | 153 |         this.get('console').get('element').all('#category-listing li.highlight').removeClass('highlight');
 | 
        
           |  |  | 154 |     },
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |     /**
 | 
        
           |  |  | 157 |      * Dragging in progress.
 | 
        
           |  |  | 158 |      * @method dragDrag
 | 
        
           |  |  | 159 |      * @private
 | 
        
           |  |  | 160 |      * @param {EventFacade} e
 | 
        
           |  |  | 161 |      */
 | 
        
           |  |  | 162 |     dragDrag: function(e) {
 | 
        
           |  |  | 163 |         var y = e.target.lastXY[1];
 | 
        
           |  |  | 164 |         if (y < this.lasty) {
 | 
        
           |  |  | 165 |             this.goingup = true;
 | 
        
           |  |  | 166 |         } else {
 | 
        
           |  |  | 167 |             this.goingup = false;
 | 
        
           |  |  | 168 |         }
 | 
        
           |  |  | 169 |         this.lasty = y;
 | 
        
           |  |  | 170 |     },
 | 
        
           |  |  | 171 |   | 
        
           |  |  | 172 |     /**
 | 
        
           |  |  | 173 |      * The course has been dragged over a drop target.
 | 
        
           |  |  | 174 |      * @method dropOver
 | 
        
           |  |  | 175 |      * @private
 | 
        
           |  |  | 176 |      * @param {EventFacade} e
 | 
        
           |  |  | 177 |      */
 | 
        
           |  |  | 178 |     dropOver: function(e) {
 | 
        
           |  |  | 179 |         // Get a reference to our drag and drop nodes
 | 
        
           |  |  | 180 |         var drag = e.drag.get('node'),
 | 
        
           |  |  | 181 |             drop = e.drop.get('node'),
 | 
        
           |  |  | 182 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 183 |         if (tag === 'li' && drop.hasClass('listitem-course')) {
 | 
        
           |  |  | 184 |             if (!this.goingup) {
 | 
        
           |  |  | 185 |                 drop = drop.get('nextSibling');
 | 
        
           |  |  | 186 |                 if (!drop) {
 | 
        
           |  |  | 187 |                     drop = e.drop.get('node');
 | 
        
           |  |  | 188 |                     drop.get('parentNode').append(drag);
 | 
        
           |  |  | 189 |                     return false;
 | 
        
           |  |  | 190 |                 }
 | 
        
           |  |  | 191 |             }
 | 
        
           |  |  | 192 |             drop.get('parentNode').insertBefore(drag, drop);
 | 
        
           |  |  | 193 |             e.drop.sizeShim();
 | 
        
           |  |  | 194 |         }
 | 
        
           |  |  | 195 |     },
 | 
        
           |  |  | 196 |   | 
        
           |  |  | 197 |     /**
 | 
        
           |  |  | 198 |      * The course has been dragged over a drop target.
 | 
        
           |  |  | 199 |      * @method dropEnter
 | 
        
           |  |  | 200 |      * @private
 | 
        
           |  |  | 201 |      * @param {EventFacade} e
 | 
        
           |  |  | 202 |      */
 | 
        
           |  |  | 203 |     dropEnter: function(e) {
 | 
        
           |  |  | 204 |         var drop = e.drop.get('node'),
 | 
        
           |  |  | 205 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 206 |         if (tag === 'div') {
 | 
        
           |  |  | 207 |             drop.ancestor('li.listitem-category').addClass('highlight');
 | 
        
           |  |  | 208 |         }
 | 
        
           |  |  | 209 |     },
 | 
        
           |  |  | 210 |   | 
        
           |  |  | 211 |     /**
 | 
        
           |  |  | 212 |      * The course has been dragged off a drop target.
 | 
        
           |  |  | 213 |      * @method dropExit
 | 
        
           |  |  | 214 |      * @private
 | 
        
           |  |  | 215 |      * @param {EventFacade} e
 | 
        
           |  |  | 216 |      */
 | 
        
           |  |  | 217 |     dropExit: function(e) {
 | 
        
           |  |  | 218 |         var drop = e.drop.get('node'),
 | 
        
           |  |  | 219 |             tag = drop.get('tagName').toLowerCase();
 | 
        
           |  |  | 220 |         if (tag === 'div') {
 | 
        
           |  |  | 221 |             drop.ancestor('li.listitem-category').removeClass('highlight');
 | 
        
           |  |  | 222 |         }
 | 
        
           |  |  | 223 |     },
 | 
        
           |  |  | 224 |   | 
        
           |  |  | 225 |     /**
 | 
        
           |  |  | 226 |      * The course has been dropped on a target.
 | 
        
           |  |  | 227 |      * @method dropHit
 | 
        
           |  |  | 228 |      * @private
 | 
        
           |  |  | 229 |      * @param {EventFacade} e
 | 
        
           |  |  | 230 |      */
 | 
        
           |  |  | 231 |     dropHit: function(e) {
 | 
        
           |  |  | 232 |         var drag = e.drag.get('node'),
 | 
        
           |  |  | 233 |             drop = e.drop.get('node'),
 | 
        
           |  |  | 234 |             iscategory = (drop.ancestor('.listitem-category') !== null),
 | 
        
           |  |  | 235 |             iscourse = !iscategory && (drop.test('.listitem-course')),
 | 
        
           |  |  | 236 |             managementconsole = this.get('console'),
 | 
        
           |  |  | 237 |             categoryid,
 | 
        
           |  |  | 238 |             category,
 | 
        
           |  |  | 239 |             courseid,
 | 
        
           |  |  | 240 |             course,
 | 
        
           |  |  | 241 |             aftercourseid,
 | 
        
           |  |  | 242 |             previoussibling,
 | 
        
           |  |  | 243 |             previousid;
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |         if (!drag.test('.listitem-course')) {
 | 
        
           |  |  | 246 |             Y.log('It was not a course being dragged.', 'warn', 'moodle-course-management');
 | 
        
           |  |  | 247 |             return false;
 | 
        
           |  |  | 248 |         }
 | 
        
           |  |  | 249 |         courseid = drag.getData('id');
 | 
        
           |  |  | 250 |         if (iscategory) {
 | 
        
           |  |  | 251 |             categoryid = drop.ancestor('.listitem-category').getData('id');
 | 
        
           |  |  | 252 |             Y.log('Course ' + courseid + ' dragged into category ' + categoryid);
 | 
        
           |  |  | 253 |             category = managementconsole.getCategoryById(categoryid);
 | 
        
           |  |  | 254 |             if (category) {
 | 
        
           |  |  | 255 |                 course = managementconsole.getCourseById(courseid);
 | 
        
           |  |  | 256 |                 if (course) {
 | 
        
           |  |  | 257 |                     category.moveCourseTo(course);
 | 
        
           |  |  | 258 |                 }
 | 
        
           |  |  | 259 |             }
 | 
        
           |  |  | 260 |         } else if (iscourse || drop.ancestor('#course-listing')) {
 | 
        
           |  |  | 261 |             course = managementconsole.getCourseById(courseid);
 | 
        
           |  |  | 262 |             previoussibling = drag.get('previousSibling');
 | 
        
           |  |  | 263 |             aftercourseid = (previoussibling) ? previoussibling.getData('id') || 0 : 0;
 | 
        
           |  |  | 264 |             previousid = (this.previoussibling) ? this.previoussibling.getData('id') : 0;
 | 
        
           |  |  | 265 |             if (aftercourseid !== previousid) {
 | 
        
           |  |  | 266 |                 course.moveAfter(aftercourseid, previousid);
 | 
        
           |  |  | 267 |             }
 | 
        
           |  |  | 268 |         } else {
 | 
        
           |  |  | 269 |             Y.log('Course dropped over unhandled target.', 'info', 'moodle-course-management');
 | 
        
           |  |  | 270 |         }
 | 
        
           |  |  | 271 |     }
 | 
        
           |  |  | 272 | };
 | 
        
           |  |  | 273 | Y.extend(DragDrop, Y.Base, DragDrop.prototype);
 |