| 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'),
|
|
|
60 |
categoryul = (categorylisting) ? categorylisting.one('ul.ml') : null,
|
|
|
61 |
courseul = (courselisting) ? courselisting.one('ul.ml') : null,
|
|
|
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);
|