3
Copyright 2011 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
7
YUI.add('dd-drop', function(Y) {
11
* Provides the ability to create a Drop Target.
16
* Provides the ability to create a Drop Target.
25
OFFSET_HEIGHT = 'offsetHeight',
26
OFFSET_WIDTH = 'offsetWidth',
29
* @description Fires when a drag element is over this target.
30
* @param {EventFacade} event An Event Facade object with the following specific property added:
32
* <dt>drop</dt><dd>The drop object at the time of the event.</dd>
33
* <dt>drag</dt><dd>The drag object at the time of the event.</dd>
38
EV_DROP_OVER = 'drop:over',
41
* @description Fires when a drag element enters this target.
42
* @param {EventFacade} event An Event Facade object with the following specific property added:
44
* <dt>drop</dt><dd>The drop object at the time of the event.</dd>
45
* <dt>drag</dt><dd>The drag object at the time of the event.</dd>
50
EV_DROP_ENTER = 'drop:enter',
53
* @description Fires when a drag element exits this target.
54
* @param {EventFacade} event An Event Facade object
58
EV_DROP_EXIT = 'drop:exit',
62
* @description Fires when a draggable node is dropped on this Drop Target. (Fired from dd-ddm-drop)
63
* @param {EventFacade} event An Event Facade object with the following specific property added:
65
* <dt>drop</dt><dd>The best guess on what was dropped on.</dd>
66
* <dt>drag</dt><dd>The drag object at the time of the event.</dd>
67
* <dt>others</dt><dd>An array of all the other drop targets that was dropped on.</dd>
75
this._lazyAddAttrs = false;
76
Drop.superclass.constructor.apply(this, arguments);
80
Y.on('domready', Y.bind(function() {
81
Y.later(100, this, this._createShim);
86
if (Dom.getStyle(this.el, 'position') == 'fixed') {
87
Event.on(window, 'scroll', function() {
99
* @description Y.Node instanace to use as the element to make a Drop Target
103
setter: function(node) {
106
Y.error('DD.Drop: Invalid Node Given: ' + node);
113
* @description Array of groups to add this drop into.
118
setter: function(g) {
120
Y.each(g, function(v, k) {
121
this._groups[v] = true;
128
* @description CSS style padding to make the Drop Target bigger than the node.
133
setter: function(p) {
134
return DDM.cssSizestoObject(p);
139
* @description Set to lock this drop element.
144
setter: function(lock) {
146
this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-locked');
148
this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-locked');
156
* @description Controls the default bubble parent for this Drop instance. Default: Y.DD.DDM. Set to false to disable bubbling. Use bubbleTargets in config.
160
setter: function(t) {
161
Y.log('bubbles is deprecated use bubbleTargets: HOST', 'warn', 'dd');
169
* @description Use the Drop shim. Default: true
174
setter: function(v) {
175
Y.DD.DDM._noShim = !v;
181
Y.extend(Drop, Y.Base, {
184
* @property _bubbleTargets
185
* @description The default bubbleTarget for this object. Default: Y.DD.DDM
187
_bubbleTargets: Y.DD.DDM,
190
* @description Add this Drop instance to a group, this should be used for on-the-fly group additions.
191
* @param {String} g The group to add this Drop Instance to.
195
addToGroup: function(g) {
196
this._groups[g] = true;
200
* @method removeFromGroup
201
* @description Remove this Drop instance from a group, this should be used for on-the-fly group removals.
202
* @param {String} g The group to remove this Drop Instance from.
206
removeFromGroup: function(g) {
207
delete this._groups[g];
212
* @method _createEvents
213
* @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
215
_createEvents: function() {
224
Y.each(ev, function(v, k) {
238
* @description Flag for determining if the target is valid in this operation.
245
* @description The groups this target belongs to.
251
* @description Node reference to the targets shim
257
* @description A region object associated with this target, used for checking regions while dragging.
262
* @property overTarget
263
* @description This flag is tripped when a drag element is over this target.
269
* @description Check if this target is in one of the supplied groups.
270
* @param {Array} groups The groups to check against
273
inGroup: function(groups) {
276
Y.each(groups, function(v, k) {
277
if (this._groups[v]) {
286
* @method initializer
287
* @description Private lifecycle method
289
initializer: function(cfg) {
290
Y.later(100, this, this._createEvents);
292
var node = this.get(NODE), id;
293
if (!node.get('id')) {
297
node.addClass(DDM.CSS_PREFIX + '-drop');
298
//Shouldn't have to do this..
299
this.set('groups', this.get('groups'));
304
* @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
306
destructor: function() {
307
DDM._unregTarget(this);
308
if (this.shim && (this.shim !== this.get(NODE))) {
309
this.shim.detachAll();
313
this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop');
318
* @method _deactivateShim
319
* @description Removes classes from the target, resets some flags and sets the shims deactive position [-999, -999]
321
_deactivateShim: function() {
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');
329
if (this.get('useShim')) {
330
this.shim.setStyles({
336
this.overTarget = false;
340
* @method _activateShim
341
* @description Activates the shim and adds some interaction CSS classes
343
_activateShim: function() {
344
if (!DDM.activeDrag) {
345
return false; //Nothing is dragging, no reason to activate.
347
if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
350
if (this.get('lock')) {
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');
360
this.overTarget = false;
361
if (!this.get('useShim')) {
362
this.shim = this.get(NODE);
366
DDM._removeValid(this);
367
node.removeClass(DDM.CSS_PREFIX + '-drop-active-valid');
368
node.addClass(DDM.CSS_PREFIX + '-drop-active-invalid');
373
* @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..
375
sizeShim: function() {
376
if (!DDM.activeDrag) {
377
return false; //Nothing is dragging, no reason to activate.
379
if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
382
//if (this.get('lock') || !this.get('useShim')) {
383
if (this.get('lock')) {
387
Y.later(100, this, this.sizeShim);
390
var node = this.get(NODE),
391
nh = node.get(OFFSET_HEIGHT),
392
nw = node.get(OFFSET_WIDTH),
394
p = this.get('padding'),
399
nw = nw + p.left + p.right;
400
nh = nh + p.top + p.bottom;
401
xy[0] = xy[0] - p.left;
402
xy[1] = xy[1] - p.top;
405
if (DDM.activeDrag.get('dragMode') === DDM.INTERSECT) {
406
//Intersect Mode, make the shim bigger
408
dH = dd.get(NODE).get(OFFSET_HEIGHT);
409
dW = dd.get(NODE).get(OFFSET_WIDTH);
413
xy[0] = xy[0] - (dW - dd.deltaXY[0]);
414
xy[1] = xy[1] - (dH - dd.deltaXY[1]);
418
if (this.get('useShim')) {
419
//Set the style on the shim
420
this.shim.setStyles({
428
//Create the region to be used by intersect when a drag node is over us.
441
* @method _createShim
442
* @description Creates the Target shim and adds it to the DDM's playground..
444
_createShim: function() {
445
//No playground, defer
447
Y.later(10, this, this._createShim);
450
//Shim already here, cancel
454
var s = this.get('node');
456
if (this.get('useShim')) {
457
s = Y.Node.create('<div id="' + this.get(NODE).get('id') + '_shim"></div>');
459
height: this.get(NODE).get(OFFSET_HEIGHT) + 'px',
460
width: this.get(NODE).get(OFFSET_WIDTH) + 'px',
461
backgroundColor: 'yellow',
470
DDM._pg.appendChild(s);
472
s.on('mouseover', Y.bind(this._handleOverEvent, this));
473
s.on('mouseout', Y.bind(this._handleOutEvent, this));
481
* @method _handleOverTarget
482
* @description This handles the over target call made from this object or from the DDM
484
_handleTargetOver: function() {
485
if (DDM.isOverTarget(this)) {
486
this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-over');
487
DDM.activeDrop = this;
488
DDM.otherDrops[this] = this;
489
if (this.overTarget) {
490
DDM.activeDrag.fire('drag:over', { drop: this, drag: DDM.activeDrag });
491
this.fire(EV_DROP_OVER, { drop: this, drag: DDM.activeDrag });
493
//Prevent an enter before a start..
494
if (DDM.activeDrag.get('dragging')) {
495
this.overTarget = true;
496
this.fire(EV_DROP_ENTER, { drop: this, drag: DDM.activeDrag });
497
DDM.activeDrag.fire('drag:enter', { drop: this, drag: DDM.activeDrag });
498
DDM.activeDrag.get(NODE).addClass(DDM.CSS_PREFIX + '-drag-over');
499
//TODO - Is this needed??
500
//DDM._handleTargetOver();
509
* @method _handleOverEvent
510
* @description Handles the mouseover DOM event on the Target Shim
512
_handleOverEvent: function() {
513
this.shim.setStyle('zIndex', '999');
514
DDM._addActiveShim(this);
518
* @method _handleOutEvent
519
* @description Handles the mouseout DOM event on the Target Shim
521
_handleOutEvent: function() {
522
this.shim.setStyle('zIndex', '1');
523
DDM._removeActiveShim(this);
528
* @description Handles out of target calls/checks
530
_handleOut: function(force) {
531
if (!DDM.isOverTarget(this) || force) {
532
if (this.overTarget) {
533
this.overTarget = false;
535
DDM._removeActiveShim(this);
537
if (DDM.activeDrag) {
538
this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-over');
539
DDM.activeDrag.get(NODE).removeClass(DDM.CSS_PREFIX + '-drag-over');
540
this.fire(EV_DROP_EXIT);
541
DDM.activeDrag.fire('drag:exit', { drop: this });
542
delete DDM.otherDrops[this];
554
}, '3.4.1' ,{skinnable:false, requires:['dd-ddm-drop', 'dd-drag']});