~smagoun/whoopsie/whoopsie-lp1017637

« back to all changes in this revision

Viewing changes to backend/stats/static/js/yui/build/sortable/sortable.js

  • Committer: Evan Dandrea
  • Date: 2012-05-09 05:53:45 UTC
  • Revision ID: evan.dandrea@canonical.com-20120509055345-z2j41tmcbf4as5uf
The backend now lives in lp:daisy and the website (errors.ubuntu.com) now lives in lp:errors.

Show diffs side-by-side

added added

removed removed

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