~ahasenack/lazr-js/lazr-js-11.03-packaging

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/sortable/sortable.js

  • Committer: Sidnei da Silva
  • Date: 2010-04-08 14:44:59 UTC
  • mfrom: (166.8.13 yui-3.1.0)
  • Revision ID: sidnei.da.silva@canonical.com-20100408144459-qozybvnrgr7iee7k
Merged yui-3.1.0 [r=therve,rockstar] [f=558457].

Updates lazr-js to use YUI 3.1.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.com/yui/license.html
 
5
version: 3.1.0
 
6
build: 2026
 
7
*/
 
8
YUI.add('sortable', function(Y) {
 
9
 
 
10
 
 
11
    /**
 
12
     * The class allows you to create a Drag & Drop reordered list.
 
13
     * @module sortable
 
14
     */     
 
15
    /**
 
16
     * The class allows you to create a Drag & Drop reordered list.
 
17
     * @class Sortable
 
18
     * @extends Base
 
19
     * @constructor
 
20
     */
 
21
 
 
22
 
 
23
    var Sortable = function(o) {
 
24
        Sortable.superclass.constructor.apply(this, arguments);
 
25
    },
 
26
    CURRENT_NODE = 'currentNode',
 
27
    OPACITY_NODE = 'opacityNode',
 
28
    CONT = 'container',
 
29
    ID = 'id',
 
30
    ZINDEX = 'zIndex',
 
31
    OPACITY = 'opacity',
 
32
    PARENT_NODE = 'parentNode',
 
33
    NODES = 'nodes',
 
34
    NODE = 'node';
 
35
 
 
36
 
 
37
    Y.extend(Sortable, Y.Base, {
 
38
        /**
 
39
        * @property delegate
 
40
        * @type DD.Delegate
 
41
        * @description A reference to the DD.Delegate instance.
 
42
        */
 
43
        delegate: null,
 
44
        initializer: function() {
 
45
            var id = 'sortable-' + Y.guid(), c,
 
46
                delConfig = {
 
47
                    container: this.get(CONT),
 
48
                    nodes: this.get(NODES),
 
49
                    target: true,
 
50
                    invalid: this.get('invalid'),
 
51
                    dragConfig: {
 
52
                        groups: [ id ]
 
53
                    }
 
54
                }, del;
 
55
 
 
56
            if (this.get('handles')) {
 
57
                delConfig.handles = this.get('handles');
 
58
            }
 
59
            del = new Y.DD.Delegate(delConfig);
 
60
 
 
61
            this.set(ID, id);
 
62
 
 
63
            del.dd.plug(Y.Plugin.DDProxy, {
 
64
                moveOnEnd: false,
 
65
                cloneNode: true
 
66
            });
 
67
 
 
68
            c = new Y.DD.Drop({
 
69
                node: this.get(CONT),
 
70
                bubbleTarget: del,
 
71
                groups: del.dd.get('groups')
 
72
            }).on('drop:over', Y.bind(this._onDropOver, 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);
 
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 _onDropOver
 
98
        * @param Event e The Event Object
 
99
        * @description Handles the DropOver event to append a drop node to an empty target
 
100
        */
 
101
        _onDropOver: function(e) {
 
102
            if (!e.drop.get(NODE).test(this.get(NODES))) {
 
103
                var nodes = e.drop.get(NODE).all(this.get(NODES));
 
104
                if (nodes.size() === 0) {
 
105
                    e.drop.get(NODE).append(e.drag.get(NODE));
 
106
                }
 
107
            }
 
108
        },
 
109
        /**
 
110
        * @private
 
111
        * @method _onDragOver
 
112
        * @param Event e The Event Object
 
113
        * @description Handles the DragOver event that moves the object in the list or to another list.
 
114
        */
 
115
        _onDragOver: function(e) {
 
116
            if (!e.drop.get(NODE).test(this.get(NODES))) {
 
117
                return;
 
118
            }
 
119
            if (e.drag.get(NODE) == e.drop.get(NODE)) {
 
120
                return;
 
121
            }
 
122
 
 
123
            switch (this.get('moveType').toLowerCase()) {
 
124
                case 'insert':
 
125
                    var dir = ((this._up) ? 'before' : 'after');
 
126
                    e.drop.get(NODE).insert(e.drag.get(NODE), dir);
 
127
                    break;
 
128
                case 'swap':
 
129
                    Y.DD.DDM.swapNode(e.drag, e.drop);
 
130
                    break;
 
131
                case 'move':
 
132
                case 'copy':
 
133
                    var dropsort = Y.Sortable.getSortable(e.drop.get(NODE).get(PARENT_NODE)),
 
134
                        oldNode, newNode;
 
135
 
 
136
                    if (!dropsort) {
 
137
                        return;
 
138
                    }
 
139
                    
 
140
                    Y.DD.DDM.getDrop(e.drag.get(NODE)).addToGroup(dropsort.get(ID));
 
141
 
 
142
                    //Same List
 
143
                    if (e.drag.get(NODE).get(PARENT_NODE).contains(e.drop.get(NODE))) {
 
144
                        Y.DD.DDM.swapNode(e.drag, e.drop);
 
145
                    } else {
 
146
                        if (this.get('moveType') == 'copy') {
 
147
                            //New List
 
148
                            oldNode = e.drag.get(NODE);
 
149
                            newNode = oldNode.cloneNode(true);
 
150
 
 
151
                            newNode.set(ID, '');
 
152
                            e.drag.set(NODE, newNode);
 
153
                            dropsort.delegate.createDrop(newNode, [dropsort.get(ID)]);
 
154
                            oldNode.setStyles({
 
155
                                top: '',
 
156
                                left: ''
 
157
                            });
 
158
                        }
 
159
                        e.drop.get(NODE).insert(e.drag.get(NODE), 'before');
 
160
                    }
 
161
                    break;
 
162
            }
 
163
        },
 
164
        /**
 
165
        * @private
 
166
        * @method _onDragStart
 
167
        * @param Event e The Event Object
 
168
        * @description Handles the DragStart event and initializes some settings.
 
169
        */
 
170
        _onDragStart: function(e) {
 
171
            this.delegate.get('lastNode').setStyle(ZINDEX, '');
 
172
            this.delegate.get(this.get(OPACITY_NODE)).setStyle(OPACITY, this.get(OPACITY));
 
173
            this.delegate.get(CURRENT_NODE).setStyle(ZINDEX, '999');
 
174
        },
 
175
        /**
 
176
        * @private
 
177
        * @method _onDragEnd
 
178
        * @param Event e The Event Object
 
179
        * @description Handles the DragEnd event that cleans up the settings in the drag:start event.
 
180
        */
 
181
        _onDragEnd: function(e) {
 
182
            this.delegate.get(this.get(OPACITY_NODE)).setStyle(OPACITY, 1);
 
183
            this.delegate.get(CURRENT_NODE).setStyles({
 
184
                top: '',
 
185
                left: ''
 
186
            });
 
187
            this.sync();
 
188
        },
 
189
        /**
 
190
        * @method plug
 
191
        * @param Class cls The class to plug
 
192
        * @param Object config The class config
 
193
        * @description Passthrough to the DD.Delegate.ddplug method
 
194
        * @chainable
 
195
        */
 
196
        plug: function(cls, config) {
 
197
            this.delegate.dd.plug(cls, config);
 
198
            return this;
 
199
        },
 
200
        /**
 
201
        * @method plug
 
202
        * @description Passthrough to the DD.Delegate syncTargets method.
 
203
        * @chainable
 
204
        */
 
205
        sync: function() {
 
206
            this.delegate.syncTargets();
 
207
            return this;
 
208
        },
 
209
        destructor: function() {
 
210
            this.delegate.destroy();
 
211
            Sortable.unreg(this);
 
212
        },
 
213
        /**
 
214
        * @method join
 
215
        * @param Sortable sel The sortable list to join with
 
216
        * @param String type The type of join to do: full, inner, outer, none. Default: full
 
217
        * @description Join this Sortable with another Sortable instance.
 
218
        * <ul>
 
219
        *   <li>full: Exchange nodes with both lists.</li>
 
220
        *   <li>inner: Items can go into this list from the joined list.</li>
 
221
        *   <li>outer: Items can go out of the joined list into this list.</li>
 
222
        *   <li>none: Removes the join.</li>
 
223
        * </ul>
 
224
        * @chainable
 
225
        */
 
226
        join: function(sel, type) {
 
227
            if (!(sel instanceof Y.Sortable)) {
 
228
                Y.error('Sortable: join needs a Sortable Instance');
 
229
                return this;
 
230
            }
 
231
            if (!type) {
 
232
                type = 'full';
 
233
            }
 
234
            type = type.toLowerCase();
 
235
            var method = '_join_' + type;
 
236
 
 
237
            if (this[method]) {
 
238
                this[method](sel);
 
239
            }
 
240
            
 
241
            return this;
 
242
        },
 
243
        /**
 
244
        * @private
 
245
        * @method _join_none
 
246
        * @param Sortable sel The Sortable to remove the join from
 
247
        * @description Removes the join with the passed Sortable.
 
248
        */
 
249
        _join_none: function(sel) {
 
250
            this.delegate.dd.removeFromGroup(sel.get(ID));
 
251
            sel.delegate.dd.removeFromGroup(this.get(ID));
 
252
        },
 
253
        /**
 
254
        * @private
 
255
        * @method _join_full
 
256
        * @param Sortable sel The sortable list to join with
 
257
        * @description Joins both of the Sortables together.
 
258
        */
 
259
        _join_full: function(sel) {
 
260
            this.delegate.dd.addToGroup(sel.get(ID));
 
261
            sel.delegate.dd.addToGroup(this.get(ID));
 
262
        },
 
263
        /**
 
264
        * @private
 
265
        * @method _join_outer
 
266
        * @param Sortable sel The sortable list to join with
 
267
        * @description Allows this Sortable to accept items from the passed Sortable.
 
268
        */
 
269
        _join_outer: function(sel) {
 
270
            this.delegate.dd.addToGroup(sel.get(ID));
 
271
        },
 
272
        /**
 
273
        * @private
 
274
        * @method _join_inner
 
275
        * @param Sortable sel The sortable list to join with
 
276
        * @description Allows this Sortable to give items to the passed Sortable.
 
277
        */
 
278
        _join_inner: function(sel) {
 
279
            sel.delegate.dd.addToGroup(this.get(ID));
 
280
        }
 
281
    }, {
 
282
        NAME: 'sortable',
 
283
        ATTRS: {
 
284
            /**
 
285
            * @attribute handles
 
286
            * @description Drag handles to pass on to the internal DD.Delegate instance.
 
287
            * @type Array
 
288
            */    
 
289
            handles: {
 
290
                value: false
 
291
            },
 
292
            /**
 
293
            * @attribute container
 
294
            * @description A selector query to get the container to listen for mousedown events on. All "nodes" should be a child of this container.
 
295
            * @type String
 
296
            */    
 
297
            container: {
 
298
                value: 'body'
 
299
            },
 
300
            /**
 
301
            * @attribute nodes
 
302
            * @description A selector query to get the children of the "container" to make draggable elements from.
 
303
            * @type String
 
304
            */        
 
305
            nodes: {
 
306
                value: '.dd-draggable'
 
307
            },
 
308
            /**
 
309
            * @attribute opacity
 
310
            * @description The ocpacity to test the proxy item to when dragging.
 
311
            * @type String
 
312
            */        
 
313
            opacity: {
 
314
                value: '.75'
 
315
            },
 
316
            /**
 
317
            * @attribute opacityNode
 
318
            * @description The node to set opacity on when dragging (dragNode or currentNode). Default: currentNode.
 
319
            * @type String
 
320
            */        
 
321
            opacityNode: {
 
322
                value: 'currentNode'
 
323
            },
 
324
            /**
 
325
            * @attribute id
 
326
            * @description The id of this sortable, used to get a reference to this sortable list from another list.
 
327
            * @type String
 
328
            */        
 
329
            id: {
 
330
                value: null
 
331
            },
 
332
            /**
 
333
            * @attribute moveType
 
334
            * @description How should an item move to another list: insert, swap, move, copy. Default: insert
 
335
            * @type String
 
336
            */        
 
337
            moveType: {
 
338
                value: 'insert'
 
339
            },
 
340
            /**
 
341
            * @attribute invalid
 
342
            * @description A selector string to test if a list item is invalid and not sortable
 
343
            * @type String
 
344
            */        
 
345
            invalid: {
 
346
                value: ''
 
347
            }
 
348
        },
 
349
        /**
 
350
        * @static
 
351
        * @property _sortables
 
352
        * @private
 
353
        * @type Array
 
354
        * @description Hash map of all Sortables on the page.
 
355
        */
 
356
        _sortables: [],
 
357
        /**
 
358
        * @static
 
359
        * @method getSortable
 
360
        * @param {String|Node} node The node instance or selector string to use to find a Sortable instance.
 
361
        * @description Get a sortable instance back from a node reference or a selector string.
 
362
        */
 
363
        getSortable: function(node) {
 
364
            var s = null;
 
365
            node = Y.one(node);
 
366
            Y.each(Sortable._sortables, function(v) {
 
367
                if (node.test(v.get(CONT))) {
 
368
                    s = v;
 
369
                }
 
370
            });
 
371
            return s;
 
372
        },
 
373
        /**
 
374
        * @static
 
375
        * @method reg
 
376
        * @param Sortable s A Sortable instance.
 
377
        * @description Register a Sortable instance with the singleton to allow lookups later.
 
378
        */
 
379
        reg: function(s) {
 
380
            Sortable._sortables.push(s);
 
381
        },
 
382
        /**
 
383
        * @static
 
384
        * @method unreg
 
385
        * @param Sortable s A Sortable instance.
 
386
        * @description Unregister a Sortable instance with the singleton.
 
387
        */
 
388
        unreg: function(s) {
 
389
            Y.each(Sortable._sortables, function(v, k) {
 
390
                if (v === s) {
 
391
                    Sortable._sortables[k] = null;
 
392
                    delete Sortable._sortables[k];
 
393
                }
 
394
            });
 
395
        }
 
396
    });
 
397
 
 
398
    Y.Sortable = Sortable;
 
399
 
 
400
 
 
401
 
 
402
}, '3.1.0' ,{requires:['dd-delegate', 'dd-drop-plugin', 'dd-proxy']});