~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/yuilib/3.9.1/build/dd-drop/dd-drop.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

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