Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('sortable', function (Y, NAME) {
2
 
3
 
4
    /**
5
     * The class allows you to create a Drag & Drop reordered list.
6
     * @module sortable
7
     */
8
    /**
9
     * The class allows you to create a Drag & Drop reordered list.
10
     * @class Sortable
11
     * @extends Base
12
     * @constructor
13
     */
14
 
15
 
16
    var Sortable = function() {
17
        Sortable.superclass.constructor.apply(this, arguments);
18
    },
19
    CURRENT_NODE = 'currentNode',
20
    OPACITY_NODE = 'opacityNode',
21
    CONT = 'container',
22
    ID = 'id',
23
    ZINDEX = 'zIndex',
24
    OPACITY = 'opacity',
25
    PARENT_NODE = 'parentNode',
26
    NODES = 'nodes',
27
    NODE = 'node';
28
 
29
 
30
    Y.extend(Sortable, Y.Base, {
31
        /**
32
        * @property delegate
33
        * @type DD.Delegate
34
        * @description A reference to the DD.Delegate instance.
35
        */
36
        delegate: null,
37
        /**
38
        * @property drop
39
        * @type DD.Drop
40
        * @description A reference to the DD.Drop instance
41
        */
42
        drop: null,
43
        initializer: function() {
44
            var id = 'sortable-' + Y.guid(),
45
                delConfig = {
46
                    container: this.get(CONT),
47
                    nodes: this.get(NODES),
48
                    target: true,
49
                    invalid: this.get('invalid'),
50
                    dragConfig: {
51
                        groups: [ id ]
52
                    }
53
                }, del;
54
 
55
            if (this.get('handles')) {
56
                delConfig.handles = this.get('handles');
57
            }
58
            del = new Y.DD.Delegate(delConfig);
59
 
60
            this.set(ID, id);
61
 
62
            del.dd.plug(Y.Plugin.DDProxy, {
63
                moveOnEnd: false,
64
                cloneNode: true
65
            });
66
 
67
            this.drop =  new Y.DD.Drop({
68
                node: this.get(CONT),
69
                bubbleTarget: del,
70
                groups: del.dd.get('groups')
71
            });
72
            this.drop.on('drop:enter', Y.bind(this._onDropEnter, this));
73
 
74
            del.on({
75
                'drag:start': Y.bind(this._onDragStart, this),
76
                'drag:end': Y.bind(this._onDragEnd, this),
77
                'drag:over': Y.bind(this._onDragOver, this),
78
                'drag:drag': Y.bind(this._onDrag, this)
79
            });
80
 
81
            this.delegate = del;
82
            Sortable.reg(this, id);
83
        },
84
        _up: null,
85
        _y: null,
86
        _onDrag: function(e) {
87
            if (e.pageY < this._y) {
88
                this._up = true;
89
            } else if (e.pageY > this._y) {
90
                this._up = false;
91
            }
92
 
93
            this._y = e.pageY;
94
        },
95
        /**
96
        * @private
97
        * @method _onDropEnter
98
        * @param Event e The Event Object
99
        * @description Handles the DropEnter event to append a new node to a target.
100
        */
101
        _onDropEnter: function(e) {
102
            var dropNode = e.drop.get(NODE),
103
                dragNode = e.drag.get(NODE);
104
 
105
            if (!dropNode.test(this.get(NODES)) &&
106
                !dragNode.get(PARENT_NODE).compareTo(dropNode)) {
107
                dropNode.append(dragNode);
108
            }
109
        },
110
        /**
111
        * @private
112
        * @method _onDragOver
113
        * @param Event e The Event Object
114
        * @description Handles the DragOver event that moves the object in the list or to another list.
115
        */
116
        _onDragOver: function(e) {
117
            if (!e.drop.get(NODE).test(this.get(NODES))) {
118
                return;
119
            }
120
            if (e.drag.get(NODE) === e.drop.get(NODE)) {
121
                return;
122
            }
123
            // is drop a child of drag?
124
            if (e.drag.get(NODE).contains(e.drop.get(NODE))) {
125
                return;
126
            }
127
            var same = false, dir, oldNode, newNode, dropsort, dropNode,
128
                moveType = this.get('moveType').toLowerCase();
129
 
130
            if (e.drag.get(NODE).get(PARENT_NODE).contains(e.drop.get(NODE))) {
131
                same = true;
132
            }
133
            if (same && moveType === 'move') {
134
                moveType = 'insert';
135
            }
136
            switch (moveType) {
137
                case 'insert':
138
                    dir = ((this._up) ? 'before' : 'after');
139
                    dropNode = e.drop.get(NODE);
140
                    if (Y.Sortable._test(dropNode, this.get(CONT))) {
141
                        dropNode.append(e.drag.get(NODE));
142
                    } else {
143
                        dropNode.insert(e.drag.get(NODE), dir);
144
                    }
145
                    break;
146
                case 'swap':
147
                    Y.DD.DDM.swapNode(e.drag, e.drop);
148
                    break;
149
                case 'move':
150
                case 'copy':
151
                    dropsort = Y.Sortable.getSortable(e.drop.get(NODE).get(PARENT_NODE));
152
 
153
                    if (!dropsort) {
154
                        Y.log('No delegate parent found', 'error', 'sortable');
155
                        return;
156
                    }
157
 
158
                    Y.DD.DDM.getDrop(e.drag.get(NODE)).addToGroup(dropsort.get(ID));
159
 
160
                    //Same List
161
                    if (same) {
162
                        Y.DD.DDM.swapNode(e.drag, e.drop);
163
                    } else {
164
                        if (this.get('moveType') === 'copy') {
165
                            //New List
166
                            oldNode = e.drag.get(NODE);
167
                            newNode = oldNode.cloneNode(true);
168
 
169
                            newNode.set(ID, '');
170
                            e.drag.set(NODE, newNode);
171
                            dropsort.delegate.createDrop(newNode, [dropsort.get(ID)]);
172
                            oldNode.setStyles({
173
                                top: '',
174
                                left: ''
175
                            });
176
                        }
177
                        e.drop.get(NODE).insert(e.drag.get(NODE), 'before');
178
                    }
179
                    break;
180
            }
181
 
182
            this.fire(moveType, { same: same, drag: e.drag, drop: e.drop });
183
            this.fire('moved', { same: same, drag: e.drag, drop: e.drop });
184
        },
185
        /**
186
        * @private
187
        * @method _onDragStart
188
        * @param Event e The Event Object
189
        * @description Handles the DragStart event and initializes some settings.
190
        */
191
        _onDragStart: function() {
192
            var del = this.delegate,
193
                lastNode = del.get('lastNode');
194
            if (lastNode && lastNode.getDOMNode()) {
195
                lastNode.setStyle(ZINDEX, '');
196
            }
197
            del.get(this.get(OPACITY_NODE)).setStyle(OPACITY, this.get(OPACITY));
198
            del.get(CURRENT_NODE).setStyle(ZINDEX, '999');
199
        },
200
        /**
201
        * @private
202
        * @method _onDragEnd
203
        * @param Event e The Event Object
204
        * @description Handles the DragEnd event that cleans up the settings in the drag:start event.
205
        */
206
        _onDragEnd: function() {
207
            this.delegate.get(this.get(OPACITY_NODE)).setStyle(OPACITY, 1);
208
            this.delegate.get(CURRENT_NODE).setStyle(ZINDEX, '');
209
            this.delegate.get(CURRENT_NODE).setStyles({
210
                top: '',
211
                left: ''
212
            });
213
            this.sync();
214
        },
215
        /**
216
        * @method plug
217
        * @param Class cls The class to plug
218
        * @param Object config The class config
219
        * @description Passthrough to the DD.Delegate.ddplug method
220
        * @chainable
221
        */
222
        plug: function(cls, config) {
223
            //I don't like this.. Not at all, need to discuss with the team
224
            if (cls && cls.NAME.substring(0, 4).toLowerCase() === 'sort') {
225
                this.constructor.superclass.plug.call(this, cls, config);
226
            } else {
227
                this.delegate.dd.plug(cls, config);
228
            }
229
            return this;
230
        },
231
        /**
232
        * @method sync
233
        * @description Passthrough to the DD.Delegate syncTargets method.
234
        * @chainable
235
        */
236
        sync: function() {
237
            this.delegate.syncTargets();
238
            return this;
239
        },
240
        destructor: function() {
241
            this.drop.destroy();
242
            this.delegate.destroy();
243
            Sortable.unreg(this, this.get(ID));
244
        },
245
        /**
246
        * @method join
247
        * @param Sortable sel The Sortable list to join with
248
        * @param String type The type of join to do: full, inner, outer, none. Default: full
249
        * @description Join this Sortable with another Sortable instance.
250
        * <ul>
251
        *   <li>full: Exchange nodes with both lists.</li>
252
        *   <li>inner: Items can go into this list from the joined list.</li>
253
        *   <li>outer: Items can go out of the joined list into this list.</li>
254
        *   <li>none: Removes the join.</li>
255
        * </ul>
256
        * @chainable
257
        */
258
        join: function(sel, type) {
259
            if (!(sel instanceof Y.Sortable)) {
260
                Y.error('Sortable: join needs a Sortable Instance');
261
                return this;
262
            }
263
            if (!type) {
264
                type = 'full';
265
            }
266
            type = type.toLowerCase();
267
            var method = '_join_' + type;
268
 
269
            if (this[method]) {
270
                this[method](sel);
271
            }
272
 
273
            return this;
274
        },
275
        /**
276
        * @private
277
        * @method _join_none
278
        * @param Sortable sel The Sortable to remove the join from
279
        * @description Removes the join with the passed Sortable.
280
        */
281
        _join_none: function(sel) {
282
            this.delegate.dd.removeFromGroup(sel.get(ID));
283
            sel.delegate.dd.removeFromGroup(this.get(ID));
284
        },
285
        /**
286
        * @private
287
        * @method _join_full
288
        * @param Sortable sel The Sortable list to join with
289
        * @description Joins both of the Sortables together.
290
        */
291
        _join_full: function(sel) {
292
            this.delegate.dd.addToGroup(sel.get(ID));
293
            sel.delegate.dd.addToGroup(this.get(ID));
294
        },
295
        /**
296
        * @private
297
        * @method _join_outer
298
        * @param Sortable sel The Sortable list to join with
299
        * @description Allows this Sortable to accept items from the passed Sortable.
300
        */
301
        _join_outer: function(sel) {
302
            this.delegate.dd.addToGroup(sel.get(ID));
303
        },
304
        /**
305
        * @private
306
        * @method _join_inner
307
        * @param Sortable sel The Sortable list to join with
308
        * @description Allows this Sortable to give items to the passed Sortable.
309
        */
310
        _join_inner: function(sel) {
311
            sel.delegate.dd.addToGroup(this.get(ID));
312
        },
313
        /**
314
        * A custom callback to allow a user to extract some sort of id or any other data
315
        * from the node to use in the "ordering list" and then that data should be returned from the callback.
316
        * @method getOrdering
317
        * @param Function callback
318
        * @return Array
319
        */
320
        getOrdering: function(callback) {
321
            var ordering = [];
322
 
323
            if (!Y.Lang.isFunction(callback)) {
324
                callback = function (node) {
325
                    return node;
326
                };
327
            }
328
 
329
            Y.one(this.get(CONT)).all(this.get(NODES)).each(function(node) {
330
                ordering.push(callback(node));
331
            });
332
            return ordering;
333
       }
334
    }, {
335
        NAME: 'sortable',
336
        ATTRS: {
337
            /**
338
            * @attribute handles
339
            * @description Drag handles to pass on to the internal DD.Delegate instance.
340
            * @type Array
341
            */
342
            handles: {
343
                value: false
344
            },
345
            /**
346
            * @attribute container
347
            * @description A selector query to get the container to listen for mousedown events on. All "nodes" should be a child of this container.
348
            * @type String
349
            */
350
            container: {
351
                value: 'body'
352
            },
353
            /**
354
            * @attribute nodes
355
            * @description A selector query to get the children of the "container" to make draggable elements from.
356
            * @type String
357
            */
358
            nodes: {
359
                value: '.dd-draggable'
360
            },
361
            /**
362
            * @attribute opacity
363
            * @description The opacity to change the proxy item to when dragging.
364
            * @type String
365
            */
366
            opacity: {
367
                value: '.75'
368
            },
369
            /**
370
            * @attribute opacityNode
371
            * @description The node to set opacity on when dragging (dragNode or currentNode). Default: currentNode.
372
            * @type String
373
            */
374
            opacityNode: {
375
                value: 'currentNode'
376
            },
377
            /**
378
            * @attribute id
379
            * @description The id of this Sortable, used to get a reference to this Sortable list from another list.
380
            * @type String
381
            */
382
            id: {
383
                value: null
384
            },
385
            /**
386
            * @attribute moveType
387
            * @description How should an item move to another list: insert, swap, move, copy. Default: insert
388
            * @type String
389
            */
390
            moveType: {
391
                value: 'insert'
392
            },
393
            /**
394
            * @attribute invalid
395
            * @description A selector string to test if a list item is invalid and not sortable
396
            * @type String
397
            */
398
            invalid: {
399
                value: ''
400
            }
401
        },
402
        /**
403
        * @static
404
        * @property _sortables
405
        * @private
406
        * @type Object
407
        * @description Hash map of all Sortables on the page.
408
        */
409
        _sortables: {},
410
        /**
411
        * @static
412
        * @method _test
413
        * @param {Node} node The node instance to test.
414
        * @param {String|Node} test The node instance or selector string to test against.
415
        * @description Test a Node or a selector for the container
416
        */
417
        _test: function(node, test) {
418
            var ret;
419
            if (test instanceof Y.Node) {
420
                ret = (test === node);
421
            } else {
422
                ret = node.test(test);
423
            }
424
            return ret;
425
        },
426
        /**
427
        * @static
428
        * @method getSortable
429
        * @param {String|Node} node The node instance or selector string to use to find a Sortable instance.
430
        * @description Get a Sortable instance back from a node reference or a selector string.
431
        */
432
        getSortable: function(node) {
433
            var s = null,
434
                id = null;
435
            node = Y.one(node);
436
            id = node.get(ID);
437
            if(id && Y.Sortable._sortables[id]) {
438
                return Y.Sortable._sortables[id];
439
            }
440
            Y.Object.each(Y.Sortable._sortables, function(v) {
441
                if (Y.Sortable._test(node, v.get(CONT))) {
442
                    s = v;
443
                }
444
            });
445
            return s;
446
        },
447
        /**
448
        * @static
449
        * @method reg
450
        * @param Sortable s A Sortable instance.
451
        * @param String id (optional) The id of the sortable instance.
452
        * @description Register a Sortable instance with the singleton to allow lookups later.
453
        */
454
        reg: function(s, id) {
455
            if (!id) {
456
                id = s.get(ID);
457
            }
458
            Y.Sortable._sortables[id] = s;
459
        },
460
        /**
461
        * @static
462
        * @method unreg
463
        * @param Sortable s A Sortable instance.
464
        * @param String id (optional) The id of the sortable instance.
465
        * @description Unregister a Sortable instance with the singleton.
466
        */
467
        unreg: function(s, id) {
468
            if (!id) {
469
                id = s.get(ID);
470
            }
471
            if (id && Y.Sortable._sortables[id]) {
472
                delete Y.Sortable._sortables[id];
473
                return;
474
            }
475
            Y.Object.each(Y.Sortable._sortables, function(v, k) {
476
                if (v === s) {
477
                    delete Sortable._sortables[k];
478
                }
479
            });
480
        }
481
    });
482
 
483
    Y.Sortable = Sortable;
484
 
485
    /**
486
    * @event copy
487
    * @description A Sortable node was moved with a copy.
488
    * @param {EventFacade} event An Event Facade object
489
    * @param {Boolean} event.same Moved to the same list.
490
    * @param {DD.Drag} event.drag The drag instance.
491
    * @param {DD.Drop} event.drop The drop instance.
492
    */
493
    /**
494
    * @event move
495
    * @description A Sortable node was moved with a move.
496
    * @param {EventFacade} event An Event Facade object with the following specific property added:
497
    * @param {Boolean} event.same Moved to the same list.
498
    * @param {DD.Drag} event.drag The drag instance.
499
    * @param {DD.Drop} event.drop The drop instance.
500
    */
501
    /**
502
    * @event insert
503
    * @description A Sortable node was moved with an insert.
504
    * @param {EventFacade} event An Event Facade object with the following specific property added:
505
    * @param {Boolean} event.same Moved to the same list.
506
    * @param {DD.Drag} event.drag The drag instance.
507
    * @param {DD.Drop} event.drop The drop instance.
508
    */
509
    /**
510
    * @event swap
511
    * @description A Sortable node was moved with a swap.
512
    * @param {EventFacade} event An Event Facade object with the following specific property added:
513
    * @param {Boolean} event.same Moved to the same list.
514
    * @param {DD.Drag} event.drag The drag instance.
515
    * @param {DD.Drop} event.drop The drop instance.
516
    */
517
    /**
518
    * @event moved
519
    * @description A Sortable node was moved.
520
    * @param {EventFacade} event An Event Facade object with the following specific property added:
521
    * @param {Boolean} event.same Moved to the same list.
522
    * @param {DD.Drag} event.drag The drag instance.
523
    * @param {DD.Drop} event.drop The drop instance.
524
    */
525
 
526
 
527
 
528
}, '3.18.1', {"requires": ["dd-delegate", "dd-drop-plugin", "dd-proxy"]});