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
                        return;
155
                    }
156
 
157
                    Y.DD.DDM.getDrop(e.drag.get(NODE)).addToGroup(dropsort.get(ID));
158
 
159
                    //Same List
160
                    if (same) {
161
                        Y.DD.DDM.swapNode(e.drag, e.drop);
162
                    } else {
163
                        if (this.get('moveType') === 'copy') {
164
                            //New List
165
                            oldNode = e.drag.get(NODE);
166
                            newNode = oldNode.cloneNode(true);
167
 
168
                            newNode.set(ID, '');
169
                            e.drag.set(NODE, newNode);
170
                            dropsort.delegate.createDrop(newNode, [dropsort.get(ID)]);
171
                            oldNode.setStyles({
172
                                top: '',
173
                                left: ''
174
                            });
175
                        }
176
                        e.drop.get(NODE).insert(e.drag.get(NODE), 'before');
177
                    }
178
                    break;
179
            }
180
 
181
            this.fire(moveType, { same: same, drag: e.drag, drop: e.drop });
182
            this.fire('moved', { same: same, drag: e.drag, drop: e.drop });
183
        },
184
        /**
185
        * @private
186
        * @method _onDragStart
187
        * @param Event e The Event Object
188
        * @description Handles the DragStart event and initializes some settings.
189
        */
190
        _onDragStart: function() {
191
            var del = this.delegate,
192
                lastNode = del.get('lastNode');
193
            if (lastNode && lastNode.getDOMNode()) {
194
                lastNode.setStyle(ZINDEX, '');
195
            }
196
            del.get(this.get(OPACITY_NODE)).setStyle(OPACITY, this.get(OPACITY));
197
            del.get(CURRENT_NODE).setStyle(ZINDEX, '999');
198
        },
199
        /**
200
        * @private
201
        * @method _onDragEnd
202
        * @param Event e The Event Object
203
        * @description Handles the DragEnd event that cleans up the settings in the drag:start event.
204
        */
205
        _onDragEnd: function() {
206
            this.delegate.get(this.get(OPACITY_NODE)).setStyle(OPACITY, 1);
207
            this.delegate.get(CURRENT_NODE).setStyle(ZINDEX, '');
208
            this.delegate.get(CURRENT_NODE).setStyles({
209
                top: '',
210
                left: ''
211
            });
212
            this.sync();
213
        },
214
        /**
215
        * @method plug
216
        * @param Class cls The class to plug
217
        * @param Object config The class config
218
        * @description Passthrough to the DD.Delegate.ddplug method
219
        * @chainable
220
        */
221
        plug: function(cls, config) {
222
            //I don't like this.. Not at all, need to discuss with the team
223
            if (cls && cls.NAME.substring(0, 4).toLowerCase() === 'sort') {
224
                this.constructor.superclass.plug.call(this, cls, config);
225
            } else {
226
                this.delegate.dd.plug(cls, config);
227
            }
228
            return this;
229
        },
230
        /**
231
        * @method sync
232
        * @description Passthrough to the DD.Delegate syncTargets method.
233
        * @chainable
234
        */
235
        sync: function() {
236
            this.delegate.syncTargets();
237
            return this;
238
        },
239
        destructor: function() {
240
            this.drop.destroy();
241
            this.delegate.destroy();
242
            Sortable.unreg(this, this.get(ID));
243
        },
244
        /**
245
        * @method join
246
        * @param Sortable sel The Sortable list to join with
247
        * @param String type The type of join to do: full, inner, outer, none. Default: full
248
        * @description Join this Sortable with another Sortable instance.
249
        * <ul>
250
        *   <li>full: Exchange nodes with both lists.</li>
251
        *   <li>inner: Items can go into this list from the joined list.</li>
252
        *   <li>outer: Items can go out of the joined list into this list.</li>
253
        *   <li>none: Removes the join.</li>
254
        * </ul>
255
        * @chainable
256
        */
257
        join: function(sel, type) {
258
            if (!(sel instanceof Y.Sortable)) {
259
                Y.error('Sortable: join needs a Sortable Instance');
260
                return this;
261
            }
262
            if (!type) {
263
                type = 'full';
264
            }
265
            type = type.toLowerCase();
266
            var method = '_join_' + type;
267
 
268
            if (this[method]) {
269
                this[method](sel);
270
            }
271
 
272
            return this;
273
        },
274
        /**
275
        * @private
276
        * @method _join_none
277
        * @param Sortable sel The Sortable to remove the join from
278
        * @description Removes the join with the passed Sortable.
279
        */
280
        _join_none: function(sel) {
281
            this.delegate.dd.removeFromGroup(sel.get(ID));
282
            sel.delegate.dd.removeFromGroup(this.get(ID));
283
        },
284
        /**
285
        * @private
286
        * @method _join_full
287
        * @param Sortable sel The Sortable list to join with
288
        * @description Joins both of the Sortables together.
289
        */
290
        _join_full: function(sel) {
291
            this.delegate.dd.addToGroup(sel.get(ID));
292
            sel.delegate.dd.addToGroup(this.get(ID));
293
        },
294
        /**
295
        * @private
296
        * @method _join_outer
297
        * @param Sortable sel The Sortable list to join with
298
        * @description Allows this Sortable to accept items from the passed Sortable.
299
        */
300
        _join_outer: function(sel) {
301
            this.delegate.dd.addToGroup(sel.get(ID));
302
        },
303
        /**
304
        * @private
305
        * @method _join_inner
306
        * @param Sortable sel The Sortable list to join with
307
        * @description Allows this Sortable to give items to the passed Sortable.
308
        */
309
        _join_inner: function(sel) {
310
            sel.delegate.dd.addToGroup(this.get(ID));
311
        },
312
        /**
313
        * A custom callback to allow a user to extract some sort of id or any other data
314
        * from the node to use in the "ordering list" and then that data should be returned from the callback.
315
        * @method getOrdering
316
        * @param Function callback
317
        * @return Array
318
        */
319
        getOrdering: function(callback) {
320
            var ordering = [];
321
 
322
            if (!Y.Lang.isFunction(callback)) {
323
                callback = function (node) {
324
                    return node;
325
                };
326
            }
327
 
328
            Y.one(this.get(CONT)).all(this.get(NODES)).each(function(node) {
329
                ordering.push(callback(node));
330
            });
331
            return ordering;
332
       }
333
    }, {
334
        NAME: 'sortable',
335
        ATTRS: {
336
            /**
337
            * @attribute handles
338
            * @description Drag handles to pass on to the internal DD.Delegate instance.
339
            * @type Array
340
            */
341
            handles: {
342
                value: false
343
            },
344
            /**
345
            * @attribute container
346
            * @description A selector query to get the container to listen for mousedown events on. All "nodes" should be a child of this container.
347
            * @type String
348
            */
349
            container: {
350
                value: 'body'
351
            },
352
            /**
353
            * @attribute nodes
354
            * @description A selector query to get the children of the "container" to make draggable elements from.
355
            * @type String
356
            */
357
            nodes: {
358
                value: '.dd-draggable'
359
            },
360
            /**
361
            * @attribute opacity
362
            * @description The opacity to change the proxy item to when dragging.
363
            * @type String
364
            */
365
            opacity: {
366
                value: '.75'
367
            },
368
            /**
369
            * @attribute opacityNode
370
            * @description The node to set opacity on when dragging (dragNode or currentNode). Default: currentNode.
371
            * @type String
372
            */
373
            opacityNode: {
374
                value: 'currentNode'
375
            },
376
            /**
377
            * @attribute id
378
            * @description The id of this Sortable, used to get a reference to this Sortable list from another list.
379
            * @type String
380
            */
381
            id: {
382
                value: null
383
            },
384
            /**
385
            * @attribute moveType
386
            * @description How should an item move to another list: insert, swap, move, copy. Default: insert
387
            * @type String
388
            */
389
            moveType: {
390
                value: 'insert'
391
            },
392
            /**
393
            * @attribute invalid
394
            * @description A selector string to test if a list item is invalid and not sortable
395
            * @type String
396
            */
397
            invalid: {
398
                value: ''
399
            }
400
        },
401
        /**
402
        * @static
403
        * @property _sortables
404
        * @private
405
        * @type Object
406
        * @description Hash map of all Sortables on the page.
407
        */
408
        _sortables: {},
409
        /**
410
        * @static
411
        * @method _test
412
        * @param {Node} node The node instance to test.
413
        * @param {String|Node} test The node instance or selector string to test against.
414
        * @description Test a Node or a selector for the container
415
        */
416
        _test: function(node, test) {
417
            var ret;
418
            if (test instanceof Y.Node) {
419
                ret = (test === node);
420
            } else {
421
                ret = node.test(test);
422
            }
423
            return ret;
424
        },
425
        /**
426
        * @static
427
        * @method getSortable
428
        * @param {String|Node} node The node instance or selector string to use to find a Sortable instance.
429
        * @description Get a Sortable instance back from a node reference or a selector string.
430
        */
431
        getSortable: function(node) {
432
            var s = null,
433
                id = null;
434
            node = Y.one(node);
435
            id = node.get(ID);
436
            if(id && Y.Sortable._sortables[id]) {
437
                return Y.Sortable._sortables[id];
438
            }
439
            Y.Object.each(Y.Sortable._sortables, function(v) {
440
                if (Y.Sortable._test(node, v.get(CONT))) {
441
                    s = v;
442
                }
443
            });
444
            return s;
445
        },
446
        /**
447
        * @static
448
        * @method reg
449
        * @param Sortable s A Sortable instance.
450
        * @param String id (optional) The id of the sortable instance.
451
        * @description Register a Sortable instance with the singleton to allow lookups later.
452
        */
453
        reg: function(s, id) {
454
            if (!id) {
455
                id = s.get(ID);
456
            }
457
            Y.Sortable._sortables[id] = s;
458
        },
459
        /**
460
        * @static
461
        * @method unreg
462
        * @param Sortable s A Sortable instance.
463
        * @param String id (optional) The id of the sortable instance.
464
        * @description Unregister a Sortable instance with the singleton.
465
        */
466
        unreg: function(s, id) {
467
            if (!id) {
468
                id = s.get(ID);
469
            }
470
            if (id && Y.Sortable._sortables[id]) {
471
                delete Y.Sortable._sortables[id];
472
                return;
473
            }
474
            Y.Object.each(Y.Sortable._sortables, function(v, k) {
475
                if (v === s) {
476
                    delete Sortable._sortables[k];
477
                }
478
            });
479
        }
480
    });
481
 
482
    Y.Sortable = Sortable;
483
 
484
    /**
485
    * @event copy
486
    * @description A Sortable node was moved with a copy.
487
    * @param {EventFacade} event An Event Facade object
488
    * @param {Boolean} event.same Moved to the same list.
489
    * @param {DD.Drag} event.drag The drag instance.
490
    * @param {DD.Drop} event.drop The drop instance.
491
    */
492
    /**
493
    * @event move
494
    * @description A Sortable node was moved with a move.
495
    * @param {EventFacade} event An Event Facade object with the following specific property added:
496
    * @param {Boolean} event.same Moved to the same list.
497
    * @param {DD.Drag} event.drag The drag instance.
498
    * @param {DD.Drop} event.drop The drop instance.
499
    */
500
    /**
501
    * @event insert
502
    * @description A Sortable node was moved with an insert.
503
    * @param {EventFacade} event An Event Facade object with the following specific property added:
504
    * @param {Boolean} event.same Moved to the same list.
505
    * @param {DD.Drag} event.drag The drag instance.
506
    * @param {DD.Drop} event.drop The drop instance.
507
    */
508
    /**
509
    * @event swap
510
    * @description A Sortable node was moved with a swap.
511
    * @param {EventFacade} event An Event Facade object with the following specific property added:
512
    * @param {Boolean} event.same Moved to the same list.
513
    * @param {DD.Drag} event.drag The drag instance.
514
    * @param {DD.Drop} event.drop The drop instance.
515
    */
516
    /**
517
    * @event moved
518
    * @description A Sortable node was moved.
519
    * @param {EventFacade} event An Event Facade object with the following specific property added:
520
    * @param {Boolean} event.same Moved to the same list.
521
    * @param {DD.Drag} event.drag The drag instance.
522
    * @param {DD.Drop} event.drop The drop instance.
523
    */
524
 
525
 
526
 
527
}, '3.18.1', {"requires": ["dd-delegate", "dd-drop-plugin", "dd-proxy"]});