~landscape/lazr-js/trunk

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/3.0.0/build/dd/dd-drop-debug.js

  • Committer: Sidnei da Silva
  • Date: 2009-10-21 21:43:07 UTC
  • mfrom: (120.2.15 yui-3.0.0)
  • mto: (124.5.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 126.
  • Revision ID: sidnei.da.silva@canonical.com-20091021214307-mpul9404n317puk5
- Merge from yui-3.0.0, resolving conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0
 
6
build: 1549
 
7
*/
 
8
YUI.add('dd-drop', function(Y) {
 
9
 
 
10
 
 
11
    /**
 
12
     * The Drag & Drop Utility allows you to create a draggable interface efficiently, buffering you from browser-level abnormalities and enabling you to focus on the interesting logic surrounding your particular implementation. This component enables you to create a variety of standard draggable objects with just a few lines of code and then, using its extensive API, add your own specific implementation logic.
 
13
     * @module dd
 
14
     * @submodule dd-drop
 
15
     */     
 
16
    /**
 
17
     * This class provides the ability to create a Drop Target.
 
18
     * @class Drop
 
19
     * @extends Base
 
20
     * @constructor
 
21
     * @namespace DD
 
22
     */
 
23
 
 
24
    var NODE = 'node',
 
25
        DDM = Y.DD.DDM,
 
26
        OFFSET_HEIGHT = 'offsetHeight',
 
27
        OFFSET_WIDTH = 'offsetWidth',
 
28
        /**
 
29
        * @event drop:over
 
30
        * @description Fires when a drag element is over this target.
 
31
        * @bubbles DDM
 
32
        * @type {Event.Custom}
 
33
        */
 
34
        EV_DROP_OVER = 'drop:over',
 
35
        /**
 
36
        * @event drop:enter
 
37
        * @description Fires when a drag element enters this target.
 
38
        * @bubbles DDM
 
39
        * @type {Event.Custom}
 
40
        */
 
41
        EV_DROP_ENTER = 'drop:enter',
 
42
        /**
 
43
        * @event drop:exit
 
44
        * @description Fires when a drag element exits this target.
 
45
        * @bubbles DDM
 
46
        * @type {Event.Custom}
 
47
        */
 
48
        EV_DROP_EXIT = 'drop:exit',
 
49
 
 
50
        /**
 
51
        * @event drop:hit
 
52
        * @description Fires when a draggable node is dropped on this Drop Target. (Fired from dd-ddm-drop)
 
53
        * @bubbles DDM
 
54
        * @type {Event.Custom}
 
55
        */
 
56
        
 
57
 
 
58
    Drop = function() {
 
59
        this._lazyAddAttrs = false;
 
60
        Drop.superclass.constructor.apply(this, arguments);
 
61
 
 
62
 
 
63
        //DD init speed up.
 
64
        Y.on('domready', Y.bind(function() {
 
65
            Y.later(100, this, this._createShim);
 
66
        }, this));
 
67
        DDM._regTarget(this);
 
68
 
 
69
        /* TODO
 
70
        if (Dom.getStyle(this.el, 'position') == 'fixed') {
 
71
            Event.on(window, 'scroll', function() {
 
72
                this.activateShim();
 
73
            }, this, true);
 
74
        }
 
75
        */
 
76
    };
 
77
 
 
78
    Drop.NAME = 'drop';
 
79
 
 
80
    Drop.ATTRS = {
 
81
        /**
 
82
        * @attribute node
 
83
        * @description Y.Node instanace to use as the element to make a Drop Target
 
84
        * @type Node
 
85
        */        
 
86
        node: {
 
87
            setter: function(node) {
 
88
                var n = Y.Node.get(node);
 
89
                if (!n) {
 
90
                    Y.error('DD.Drop: Invalid Node Given: ' + node);
 
91
                }
 
92
                return n;               
 
93
            }
 
94
        },
 
95
        /**
 
96
        * @attribute groups
 
97
        * @description Array of groups to add this drop into.
 
98
        * @type Array
 
99
        */        
 
100
        groups: {
 
101
            value: ['default'],
 
102
            setter: function(g) {
 
103
                this._groups = {};
 
104
                Y.each(g, function(v, k) {
 
105
                    this._groups[v] = true;
 
106
                }, this);
 
107
                return g;
 
108
            }
 
109
        },   
 
110
        /**
 
111
        * @attribute padding
 
112
        * @description CSS style padding to make the Drop Target bigger than the node.
 
113
        * @type String
 
114
        */
 
115
        padding: {
 
116
            value: '0',
 
117
            setter: function(p) {
 
118
                return DDM.cssSizestoObject(p);
 
119
            }
 
120
        },
 
121
        /**
 
122
        * @attribute lock
 
123
        * @description Set to lock this drop element.
 
124
        * @type Boolean
 
125
        */        
 
126
        lock: {
 
127
            value: false,
 
128
            setter: function(lock) {
 
129
                if (lock) {
 
130
                    this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-locked');
 
131
                } else {
 
132
                    this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-locked');
 
133
                }
 
134
                return lock;
 
135
            }
 
136
        },
 
137
        /**
 
138
        * @attribute bubbles
 
139
        * @description Controls the default bubble parent for this Drop instance. Default: Y.DD.DDM. Set to false to disable bubbling.
 
140
        * @type Object
 
141
        */
 
142
        bubbles: {
 
143
            writeOnce: true,
 
144
            value: Y.DD.DDM
 
145
        }
 
146
    };
 
147
 
 
148
    Y.extend(Drop, Y.Base, {
 
149
        /**
 
150
        * @private
 
151
        * @method _createEvents
 
152
        * @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
 
153
        */
 
154
        _createEvents: function() {
 
155
            
 
156
            var ev = [
 
157
                EV_DROP_OVER,
 
158
                EV_DROP_ENTER,
 
159
                EV_DROP_EXIT,
 
160
                'drop:hit'
 
161
            ];
 
162
 
 
163
            Y.each(ev, function(v, k) {
 
164
                this.publish(v, {
 
165
                    type: v,
 
166
                    emitFacade: true,
 
167
                    preventable: false,
 
168
                    bubbles: true,
 
169
                    queuable: false,
 
170
                    prefix: 'drop'
 
171
                });
 
172
            }, this);
 
173
 
 
174
            if (this.get('bubbles')) {
 
175
                this.addTarget(this.get('bubbles'));
 
176
            }
 
177
            
 
178
        },
 
179
        /**
 
180
        * @private
 
181
        * @property _valid
 
182
        * @description Flag for determining if the target is valid in this operation.
 
183
        * @type Boolean
 
184
        */
 
185
        _valid: null,
 
186
        /**
 
187
        * @private
 
188
        * @property _groups
 
189
        * @description The groups this target belongs to.
 
190
        * @type Array
 
191
        */
 
192
        _groups: null,
 
193
        /**
 
194
        * @property shim
 
195
        * @description Node reference to the targets shim
 
196
        * @type {Object}
 
197
        */
 
198
        shim: null,
 
199
        /**
 
200
        * @property region
 
201
        * @description A region object associated with this target, used for checking regions while dragging.
 
202
        * @type Object
 
203
        */
 
204
        region: null,
 
205
        /**
 
206
        * @property overTarget
 
207
        * @description This flag is tripped when a drag element is over this target.
 
208
        * @type Boolean
 
209
        */
 
210
        overTarget: null,
 
211
        /**
 
212
        * @method inGroup
 
213
        * @description Check if this target is in one of the supplied groups.
 
214
        * @param {Array} groups The groups to check against
 
215
        * @return Boolean
 
216
        */
 
217
        inGroup: function(groups) {
 
218
            this._valid = false;
 
219
            var ret = false;
 
220
            Y.each(groups, function(v, k) {
 
221
                if (this._groups[v]) {
 
222
                    ret = true;
 
223
                    this._valid = true;
 
224
                }
 
225
            }, this);
 
226
            return ret;
 
227
        },
 
228
        /**
 
229
        * @private
 
230
        * @method initializer
 
231
        * @description Private lifecycle method
 
232
        */
 
233
        initializer: function() {
 
234
            //this._createEvents();
 
235
            Y.later(100, this, this._createEvents);
 
236
 
 
237
            var node = this.get(NODE), id;
 
238
            if (!node.get('id')) {
 
239
                id = Y.stamp(node);
 
240
                node.set('id', id);
 
241
            }
 
242
            node.addClass(DDM.CSS_PREFIX + '-drop');
 
243
            //Shouldn't have to do this..
 
244
            this.set('groups', this.get('groups'));           
 
245
        },
 
246
        /**
 
247
        * @private
 
248
        * @method destructor
 
249
        * @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
 
250
        */
 
251
        destructor: function() {
 
252
            DDM._unregTarget(this);
 
253
            if (this.shim) {
 
254
                this.shim.detachAll();
 
255
                this.shim.get('parentNode').removeChild(this.shim);
 
256
                this.shim = null;
 
257
            }
 
258
            this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop');
 
259
            this.detachAll();
 
260
        },
 
261
        /**
 
262
        * @private
 
263
        * @method _deactivateShim
 
264
        * @description Removes classes from the target, resets some flags and sets the shims deactive position [-999, -999]
 
265
        */
 
266
        _deactivateShim: function() {
 
267
            if (!this.shim) {
 
268
                return false;
 
269
            }
 
270
            this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-active-valid');
 
271
            this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-active-invalid');
 
272
            this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-over');
 
273
            this.shim.setStyles({
 
274
                top: '-999px',
 
275
                left: '-999px',
 
276
                zIndex: '1'
 
277
            });
 
278
            this.overTarget = false;
 
279
        },
 
280
        /**
 
281
        * @private
 
282
        * @method _activateShim
 
283
        * @description Activates the shim and adds some interaction CSS classes
 
284
        */
 
285
        _activateShim: function() {
 
286
            if (!DDM.activeDrag) {
 
287
                return false; //Nothing is dragging, no reason to activate.
 
288
            }
 
289
            if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
 
290
                return false;
 
291
            }
 
292
            if (this.get('lock')) {
 
293
                return false;
 
294
            }
 
295
            var node = this.get(NODE);
 
296
            //TODO Visibility Check..
 
297
            //if (this.inGroup(DDM.activeDrag.get('groups')) && this.get(NODE).isVisible()) {
 
298
            if (this.inGroup(DDM.activeDrag.get('groups'))) {
 
299
                node.removeClass(DDM.CSS_PREFIX + '-drop-active-invalid');
 
300
                node.addClass(DDM.CSS_PREFIX + '-drop-active-valid');
 
301
                DDM._addValid(this);
 
302
                this.overTarget = false;
 
303
                this.sizeShim();
 
304
            } else {
 
305
                DDM._removeValid(this);
 
306
                node.removeClass(DDM.CSS_PREFIX + '-drop-active-valid');
 
307
                node.addClass(DDM.CSS_PREFIX + '-drop-active-invalid');
 
308
            }
 
309
        },
 
310
        /**
 
311
        * @method sizeShim
 
312
        * @description Positions and sizes the shim with the raw data from the node, this can be used to programatically adjust the Targets shim for Animation..
 
313
        */
 
314
        sizeShim: function() {
 
315
            if (!DDM.activeDrag) {
 
316
                return false; //Nothing is dragging, no reason to activate.
 
317
            }
 
318
            if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
 
319
                return false;
 
320
            }
 
321
            if (this.get('lock')) {
 
322
                return false;
 
323
            }
 
324
            if (!this.shim) {
 
325
                Y.later(100, this, this.sizeShim);
 
326
                return false;
 
327
            }
 
328
            var node = this.get(NODE),
 
329
                nh = node.get(OFFSET_HEIGHT),
 
330
                nw = node.get(OFFSET_WIDTH),
 
331
                xy = node.getXY(),
 
332
                p = this.get('padding'),
 
333
                dd, dH, dW;
 
334
 
 
335
 
 
336
            //Apply padding
 
337
            nw = nw + p.left + p.right;
 
338
            nh = nh + p.top + p.bottom;
 
339
            xy[0] = xy[0] - p.left;
 
340
            xy[1] = xy[1] - p.top;
 
341
            
 
342
 
 
343
            if (DDM.activeDrag.get('dragMode') === DDM.INTERSECT) {
 
344
                //Intersect Mode, make the shim bigger
 
345
                dd = DDM.activeDrag;
 
346
                dH = dd.get(NODE).get(OFFSET_HEIGHT);
 
347
                dW = dd.get(NODE).get(OFFSET_WIDTH);
 
348
                
 
349
                nh = (nh + dH);
 
350
                nw = (nw + dW);
 
351
                xy[0] = xy[0] - (dW - dd.deltaXY[0]);
 
352
                xy[1] = xy[1] - (dH - dd.deltaXY[1]);
 
353
 
 
354
            }
 
355
            
 
356
            //Set the style on the shim
 
357
            this.shim.setStyles({
 
358
                height: nh + 'px',
 
359
                width: nw + 'px',
 
360
                top: xy[1] + 'px',
 
361
                left: xy[0] + 'px'
 
362
            });
 
363
            
 
364
            //Create the region to be used by intersect when a drag node is over us.
 
365
            this.region = {
 
366
                '0': xy[0], 
 
367
                '1': xy[1],
 
368
                area: 0,
 
369
                top: xy[1],
 
370
                right: xy[0] + nw,
 
371
                bottom: xy[1] + nh,
 
372
                left: xy[0]
 
373
            };
 
374
        },
 
375
        /**
 
376
        * @private
 
377
        * @method _createShim
 
378
        * @description Creates the Target shim and adds it to the DDM's playground..
 
379
        */
 
380
        _createShim: function() {
 
381
            //No playground, defer
 
382
            if (!DDM._pg) {
 
383
                Y.later(10, this, this._createShim);
 
384
                return;
 
385
            }
 
386
            //Shim already here, cancel
 
387
            if (this.shim) {
 
388
                return;
 
389
            }
 
390
            var s = Y.Node.create('<div id="' + this.get(NODE).get('id') + '_shim"></div>');
 
391
 
 
392
            s.setStyles({
 
393
                height: this.get(NODE).get(OFFSET_HEIGHT) + 'px',
 
394
                width: this.get(NODE).get(OFFSET_WIDTH) + 'px',
 
395
                backgroundColor: 'yellow',
 
396
                opacity: '.5',
 
397
                zIndex: '1',
 
398
                overflow: 'hidden',
 
399
                top: '-900px',
 
400
                left: '-900px',
 
401
                position:  'absolute'
 
402
            });
 
403
            DDM._pg.appendChild(s);
 
404
            this.shim = s;
 
405
 
 
406
            s.on('mouseover', Y.bind(this._handleOverEvent, this));
 
407
            s.on('mouseout', Y.bind(this._handleOutEvent, this));
 
408
        },
 
409
        /**
 
410
        * @private
 
411
        * @method _handleOverTarget
 
412
        * @description This handles the over target call made from this object or from the DDM
 
413
        */
 
414
        _handleTargetOver: function() {
 
415
            if (DDM.isOverTarget(this)) {
 
416
                this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-over');
 
417
                DDM.activeDrop = this;
 
418
                DDM.otherDrops[this] = this;
 
419
                if (this.overTarget) {
 
420
                    DDM.activeDrag.fire('drag:over', { drop: this, drag: DDM.activeDrag });
 
421
                    this.fire(EV_DROP_OVER, { drop: this, drag: DDM.activeDrag });
 
422
                } else {
 
423
                    this.overTarget = true;
 
424
                    this.fire(EV_DROP_ENTER, { drop: this, drag: DDM.activeDrag });
 
425
                    DDM.activeDrag.fire('drag:enter', { drop: this, drag: DDM.activeDrag });
 
426
                    DDM.activeDrag.get(NODE).addClass(DDM.CSS_PREFIX + '-drag-over');
 
427
                    //TODO - Is this needed??
 
428
                    //DDM._handleTargetOver();
 
429
                }
 
430
            } else {
 
431
                this._handleOut();
 
432
            }
 
433
        },
 
434
        /**
 
435
        * @private
 
436
        * @method _handleOverEvent
 
437
        * @description Handles the mouseover DOM event on the Target Shim
 
438
        */
 
439
        _handleOverEvent: function() {
 
440
            this.shim.setStyle('zIndex', '999');
 
441
            DDM._addActiveShim(this);
 
442
        },
 
443
        /**
 
444
        * @private
 
445
        * @method _handleOutEvent
 
446
        * @description Handles the mouseout DOM event on the Target Shim
 
447
        */
 
448
        _handleOutEvent: function() {
 
449
            this.shim.setStyle('zIndex', '1');
 
450
            DDM._removeActiveShim(this);
 
451
        },
 
452
        /**
 
453
        * @private
 
454
        * @method _handleOut
 
455
        * @description Handles out of target calls/checks
 
456
        */
 
457
        _handleOut: function(force) {
 
458
            if (!DDM.isOverTarget(this) || force) {
 
459
                if (this.overTarget) {
 
460
                    this.overTarget = false;
 
461
                    if (!force) {
 
462
                        DDM._removeActiveShim(this);
 
463
                    }
 
464
                    if (DDM.activeDrag) {
 
465
                        this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-over');
 
466
                        DDM.activeDrag.get(NODE).removeClass(DDM.CSS_PREFIX + '-drag-over');
 
467
                        this.fire(EV_DROP_EXIT);
 
468
                        DDM.activeDrag.fire('drag:exit', { drop: this });
 
469
                        delete DDM.otherDrops[this];
 
470
                        //if (DDM.activeDrop === this) {
 
471
                        //    DDM.activeDrop = null;
 
472
                        //}
 
473
                    }
 
474
                }
 
475
            }
 
476
        }
 
477
    });
 
478
 
 
479
    Y.DD.Drop = Drop;
 
480
 
 
481
 
 
482
 
 
483
 
 
484
 
 
485
}, '3.0.0' ,{requires:['dd-ddm-drop', 'dd-drag'], skinnable:false});