~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/dd/dd-drop.js

  • Committer: Martin Albisetti
  • Date: 2008-10-20 21:18:06 UTC
  • mfrom: (229.1.3 add-yui-3)
  • Revision ID: martin.albisetti@canonical.com-20081020211806-rzs0ya40gz9wcpoz
Added yui library to the tree. Welcome to the future. (Paul Hummer)

Show diffs side-by-side

added added

removed removed

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