src/cm/media/js/lib/yui/yui_3.0.0b1/build/dd/dd-debug.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     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.0b1
       
     6 build: 1163
       
     7 */
       
     8 YUI.add('dd-ddm-base', function(Y) {
       
     9 
       
    10 
       
    11     /**
       
    12      * Provides the base Drag Drop Manger required for making a Node draggable.
       
    13      * @module dd
       
    14      * @submodule dd-ddm-base
       
    15      */     
       
    16      /**
       
    17      * Provides the base Drag Drop Manger required for making a Node draggable.
       
    18      * @class DDM
       
    19      * @extends Base
       
    20      * @constructor
       
    21      * @namespace DD
       
    22      */
       
    23     
       
    24     var DDMBase = function() {
       
    25         DDMBase.superclass.constructor.apply(this, arguments);
       
    26     };
       
    27 
       
    28     DDMBase.NAME = 'ddm';
       
    29 
       
    30     DDMBase.ATTRS = {
       
    31         /**
       
    32         * @attribute dragCursor
       
    33         * @description The cursor to apply when dragging, if shimmed the shim will get the cursor.
       
    34         * @type String
       
    35         */
       
    36         dragCursor: {
       
    37             value: 'move'
       
    38         },
       
    39         /**
       
    40         * @attribute clickPixelThresh
       
    41         * @description The number of pixels to move to start a drag operation, default is 3.
       
    42         * @type Number
       
    43         */
       
    44         clickPixelThresh: {
       
    45             value: 3
       
    46         },
       
    47         /**
       
    48         * @attribute clickTimeThresh
       
    49         * @description The number of milliseconds a mousedown has to pass to start a drag operation, default is 1000.
       
    50         * @type Number
       
    51         */        
       
    52         clickTimeThresh: {
       
    53             value: 1000
       
    54         },
       
    55         /**
       
    56         * @attribute dragMode
       
    57         * @description This attribute only works if the dd-drop module is active. It will set the dragMode (point, intersect, strict) of all future Drag instances. 
       
    58         * @type String
       
    59         */        
       
    60         dragMode: {
       
    61             value: 'point',
       
    62             setter: function(mode) {
       
    63                 this._setDragMode(mode);
       
    64                 return mode;
       
    65             }           
       
    66         }
       
    67 
       
    68     };
       
    69 
       
    70     Y.extend(DDMBase, Y.Base, {
       
    71         /**
       
    72         * @property _active
       
    73         * @description flag set when we activate our first drag, so DDM can start listening for events.
       
    74         * @type {Boolean}
       
    75         */
       
    76         _active: null,
       
    77         /**
       
    78         * @private
       
    79         * @method _setDragMode
       
    80         * @description Handler for dragMode attribute setter.
       
    81         * @param String/Number The Number value or the String for the DragMode to default all future drag instances to.
       
    82         * @return Number The Mode to be set
       
    83         */
       
    84         _setDragMode: function(mode) {
       
    85             if (mode === null) {
       
    86                 mode = Y.DD.DDM.get('dragMode');
       
    87             }
       
    88             switch (mode) {
       
    89                 case 1:
       
    90                 case 'intersect':
       
    91                     return 1;
       
    92                 case 2:
       
    93                 case 'strict':
       
    94                     return 2;
       
    95                 case 0:
       
    96                 case 'point':
       
    97                     return 0;
       
    98             }
       
    99             return 0;       
       
   100         },
       
   101         /**
       
   102         * @property CSS_PREFIX
       
   103         * @description The PREFIX to attach to all DD CSS class names
       
   104         * @type {String}
       
   105         */
       
   106         CSS_PREFIX: 'yui-dd',
       
   107         _activateTargets: function() {},        
       
   108         /**
       
   109         * @private
       
   110         * @property _drags
       
   111         * @description Holder for all registered drag elements.
       
   112         * @type {Array}
       
   113         */
       
   114         _drags: [],
       
   115         /**
       
   116         * @property activeDrag
       
   117         * @description A reference to the currently active draggable object.
       
   118         * @type {Drag}
       
   119         */
       
   120         activeDrag: false,
       
   121         /**
       
   122         * @private
       
   123         * @method _regDrag
       
   124         * @description Adds a reference to the drag object to the DDM._drags array, called in the constructor of Drag.
       
   125         * @param {Drag} d The Drag object
       
   126         */
       
   127         _regDrag: function(d) {
       
   128             this._drags[this._drags.length] = d;
       
   129             if (!this._active) {
       
   130                 this._setupListeners();
       
   131             }
       
   132         },
       
   133         /**
       
   134         * @private
       
   135         * @method _unregDrag
       
   136         * @description Remove this drag object from the DDM._drags array.
       
   137         * @param {Drag} d The drag object.
       
   138         */
       
   139         _unregDrag: function(d) {
       
   140             var tmp = [];
       
   141             Y.each(this._drags, function(n, i) {
       
   142                 if (n !== d) {
       
   143                     tmp[tmp.length] = n;
       
   144                 }
       
   145             });
       
   146             this._drags = tmp;
       
   147         },
       
   148         /**
       
   149         * @private
       
   150         * @method _setupListeners
       
   151         * @description Add the document listeners.
       
   152         */
       
   153         _setupListeners: function() {
       
   154             this._active = true;
       
   155             var doc = Y.get(document);
       
   156             doc.on('mousemove', Y.bind(this._move, this));
       
   157             //Y.Event.nativeAdd(document, 'mousemove', Y.bind(this._move, this));
       
   158             doc.on('mouseup', Y.bind(this._end, this));
       
   159         },
       
   160         /**
       
   161         * @private
       
   162         * @method _start
       
   163         * @description Internal method used by Drag to signal the start of a drag operation
       
   164         * @param {Number} x The x position of the drag element
       
   165         * @param {Number} y The y position of the drag element
       
   166         * @param {Number} w The width of the drag element
       
   167         * @param {Number} h The height of the drag element
       
   168         */
       
   169         _start: function(x, y, w, h) {
       
   170             this.fire('ddm:start');
       
   171             this._startDrag.apply(this, arguments);
       
   172         },
       
   173         /**
       
   174         * @private
       
   175         * @method _startDrag
       
   176         * @description Factory method to be overwritten by other DDM's
       
   177         * @param {Number} x The x position of the drag element
       
   178         * @param {Number} y The y position of the drag element
       
   179         * @param {Number} w The width of the drag element
       
   180         * @param {Number} h The height of the drag element
       
   181         */
       
   182         _startDrag: function() {},
       
   183         /**
       
   184         * @private
       
   185         * @method _endDrag
       
   186         * @description Factory method to be overwritten by other DDM's
       
   187         */
       
   188         _endDrag: function() {},
       
   189         _dropMove: function() {},
       
   190         /**
       
   191         * @private
       
   192         * @method _end
       
   193         * @description Internal method used by Drag to signal the end of a drag operation
       
   194         */
       
   195         _end: function() {
       
   196             //@TODO - Here we can get a (click - drag - click - release) interaction instead of a (mousedown - drag - mouseup - release) interaction
       
   197             //Add as a config option??
       
   198             if (this.activeDrag) {
       
   199                 this._endDrag();
       
   200                 this.fire('ddm:end');
       
   201                 this.activeDrag.end.call(this.activeDrag);
       
   202                 this.activeDrag = null;
       
   203             }
       
   204         },
       
   205         /**
       
   206         * @method stopDrag
       
   207         * @description Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag.
       
   208         * @return {Self}
       
   209         * @chainable
       
   210         */       
       
   211         stopDrag: function() {
       
   212             if (this.activeDrag) {
       
   213                 this._end();
       
   214             }
       
   215             return this;
       
   216         },
       
   217         /**
       
   218         * @private
       
   219         * @method _move
       
   220         * @description Internal listener for the mousemove DOM event to pass to the Drag's move method.
       
   221         * @param {Event.Facade} ev The Dom mousemove Event
       
   222         */
       
   223         _move: function(ev) {
       
   224             if (this.activeDrag) {
       
   225                 this.activeDrag._move.call(this.activeDrag, ev);
       
   226                 this._dropMove();
       
   227             }
       
   228         },
       
   229         /**
       
   230         * //TODO Private, rename??...
       
   231         * @private
       
   232         * @method cssSizestoObject
       
   233         * @description Helper method to use to set the gutter from the attribute setter.
       
   234         * @param {String} gutter CSS style string for gutter: '5 0' (sets top and bottom to 5px, left and right to 0px), '1 2 3 4' (top 1px, right 2px, bottom 3px, left 4px)
       
   235         * @return {Object} The gutter Object Literal.
       
   236         */
       
   237         cssSizestoObject: function(gutter) {
       
   238             var x = gutter.split(' ');
       
   239                 
       
   240             switch (x.length) {
       
   241                 case 1: x[1] = x[2] = x[3] = x[0]; break;
       
   242                 case 2: x[2] = x[0]; x[3] = x[1]; break;
       
   243                 case 3: x[3] = x[1]; break;
       
   244             }
       
   245 
       
   246             return {
       
   247                 top   : parseInt(x[0],10),
       
   248                 right : parseInt(x[1],10),
       
   249                 bottom: parseInt(x[2],10),
       
   250                 left  : parseInt(x[3],10)
       
   251             };
       
   252         },
       
   253         /**
       
   254         * @method getDrag
       
   255         * @description Get a valid Drag instance back from a Node or a selector string, false otherwise
       
   256         * @param {String/Object} node The Node instance or Selector string to check for a valid Drag Object
       
   257         * @return {Object}
       
   258         */
       
   259         getDrag: function(node) {
       
   260             var drag = false,
       
   261                 n = Y.get(node);
       
   262             if (n instanceof Y.Node) {
       
   263                 Y.each(this._drags, function(v, k) {
       
   264                     if (n.compareTo(v.get('node'))) {
       
   265                         drag = v;
       
   266                     }
       
   267                 });
       
   268             }
       
   269             return drag;
       
   270         }
       
   271     });
       
   272 
       
   273     Y.namespace('DD');
       
   274     Y.DD.DDM = new DDMBase();
       
   275 
       
   276 
       
   277 
       
   278 
       
   279 
       
   280 }, '3.0.0b1' ,{requires:['node', 'base'], skinnable:false});
       
   281 YUI.add('dd-ddm', function(Y) {
       
   282 
       
   283 
       
   284     /**
       
   285      * Extends the dd-ddm-base Class to add support for the viewport shim to allow a draggable node to drag to be dragged over an iframe or any other node that traps mousemove events.
       
   286      * It is also required to have Drop Targets enabled, as the viewport shim will contain the shims for the Drop Targets.
       
   287      * @module dd
       
   288      * @submodule dd-ddm
       
   289      * @for DDM
       
   290      * @namespace DD
       
   291      */
       
   292     Y.mix(Y.DD.DDM, {
       
   293         /**
       
   294         * @private
       
   295         * @property _pg
       
   296         * @description The shim placed over the screen to track the mousemove event.
       
   297         * @type {Node}
       
   298         */
       
   299         _pg: null,
       
   300         /**
       
   301         * @private
       
   302         * @property _debugShim
       
   303         * @description Set this to true to set the shims opacity to .5 for debugging it, default: false.
       
   304         * @type {Boolean}
       
   305         */
       
   306         _debugShim: false,
       
   307         _activateTargets: function() {},
       
   308         _deactivateTargets: function() {},
       
   309         _startDrag: function() {
       
   310             if (this.activeDrag.get('useShim')) {
       
   311                 this._pg_activate();
       
   312                 this._activateTargets();
       
   313             }
       
   314         },
       
   315         _endDrag: function() {
       
   316             this._pg_deactivate();
       
   317             this._deactivateTargets();
       
   318         },
       
   319         /**
       
   320         * @private
       
   321         * @method _pg_deactivate
       
   322         * @description Deactivates the shim
       
   323         */
       
   324         _pg_deactivate: function() {
       
   325             this._pg.setStyle('display', 'none');
       
   326         },
       
   327         /**
       
   328         * @private
       
   329         * @method _pg_activate
       
   330         * @description Activates the shim
       
   331         */
       
   332         _pg_activate: function() {
       
   333             var ah = this.activeDrag.get('activeHandle'), cur = 'auto';
       
   334             if (ah) {
       
   335                 cur = ah.getStyle('cursor');
       
   336             }
       
   337             if (cur == 'auto') {
       
   338                 cur = this.get('dragCursor');
       
   339             }
       
   340             
       
   341             this._pg_size();
       
   342             this._pg.setStyles({
       
   343                 top: 0,
       
   344                 left: 0,
       
   345                 display: 'block',
       
   346                 opacity: ((this._debugShim) ? '.5' : '0'),
       
   347                 cursor: cur
       
   348             });
       
   349         },
       
   350         /**
       
   351         * @private
       
   352         * @method _pg_size
       
   353         * @description Sizes the shim on: activatation, window:scroll, window:resize
       
   354         */
       
   355         _pg_size: function() {
       
   356             if (this.activeDrag) {
       
   357                 var b = Y.get('body'),
       
   358                 h = b.get('docHeight'),
       
   359                 w = b.get('docWidth');
       
   360                 this._pg.setStyles({
       
   361                     height: h + 'px',
       
   362                     width: w + 'px'
       
   363                 });
       
   364             }
       
   365         },
       
   366         /**
       
   367         * @private
       
   368         * @method _createPG
       
   369         * @description Creates the shim and adds it's listeners to it.
       
   370         */
       
   371         _createPG: function() {
       
   372             var pg = Y.Node.create('<div></div>'),
       
   373             bd = Y.get('body');
       
   374             pg.setStyles({
       
   375                 top: '0',
       
   376                 left: '0',
       
   377                 position: 'absolute',
       
   378                 zIndex: '9999',
       
   379                 overflow: 'hidden',
       
   380                 backgroundColor: 'red',
       
   381                 display: 'none',
       
   382                 height: '5px',
       
   383                 width: '5px'
       
   384             });
       
   385             pg.set('id', Y.stamp(pg));
       
   386             pg.addClass('yui-dd-shim');
       
   387             if (bd.get('firstChild')) {
       
   388                 bd.insertBefore(pg, bd.get('firstChild'));
       
   389             } else {
       
   390                 bd.appendChild(pg);
       
   391             }
       
   392             this._pg = pg;
       
   393             this._pg.on('mouseup', Y.bind(this._end, this));
       
   394             this._pg.on('mousemove', Y.bind(this._move, this));
       
   395             
       
   396             var win = Y.get(window);
       
   397             win.on('resize', Y.bind(this._pg_size, this));
       
   398             win.on('scroll', Y.bind(this._pg_size, this));
       
   399         }   
       
   400     }, true);
       
   401 
       
   402     Y.on('domready', Y.bind(Y.DD.DDM._createPG, Y.DD.DDM));
       
   403 
       
   404 
       
   405 
       
   406 
       
   407 
       
   408 }, '3.0.0b1' ,{requires:['dd-ddm-base'], skinnable:false});
       
   409 YUI.add('dd-ddm-drop', function(Y) {
       
   410 
       
   411 
       
   412     /**
       
   413      * Extends the dd-ddm Class to add support for the placement of Drop Target shims inside the viewport shim. It also handles all Drop Target related events and interactions.
       
   414      * @module dd
       
   415      * @submodule dd-ddm-drop
       
   416      * @for DDM
       
   417      * @namespace DD
       
   418      */
       
   419 
       
   420     //TODO CSS class name for the bestMatch..
       
   421     Y.mix(Y.DD.DDM, {
       
   422         /**
       
   423         * @private
       
   424         * @property _noShim
       
   425         * @description This flag turns off the use of the mouseover/mouseout shim. It should not be used unless you know what you are doing.
       
   426         * @type {Boolean}
       
   427         */
       
   428         _noShim: false,
       
   429         /**
       
   430         * @private
       
   431         * @property _activeShims
       
   432         * @description Placeholder for all active shims on the page
       
   433         * @type {Array}
       
   434         */
       
   435         _activeShims: [],
       
   436         /**
       
   437         * @private
       
   438         * @method _hasActiveShim
       
   439         * @description This method checks the _activeShims Object to see if there is a shim active.
       
   440         * @return {Boolean}
       
   441         */
       
   442         _hasActiveShim: function() {
       
   443             if (this._noShim) {
       
   444                 return true;
       
   445             }
       
   446             return this._activeShims.length;
       
   447         },
       
   448         /**
       
   449         * @private
       
   450         * @method _addActiveShim 
       
   451         * @description Adds a Drop Target to the list of active shims
       
   452         * @param {Object} d The Drop instance to add to the list.
       
   453         */
       
   454         _addActiveShim: function(d) {
       
   455             this._activeShims[this._activeShims.length] = d;
       
   456         },
       
   457         /**
       
   458         * @private
       
   459         * @method _removeActiveShim 
       
   460         * @description Removes a Drop Target to the list of active shims
       
   461         * @param {Object} d The Drop instance to remove from the list.
       
   462         */
       
   463         _removeActiveShim: function(d) {
       
   464             var s = [];
       
   465             Y.each(this._activeShims, function(v, k) {
       
   466                 if (v._yuid !== d._yuid) {
       
   467                     s[s.length] = v;
       
   468                 }
       
   469                 
       
   470             });
       
   471             this._activeShims = s;
       
   472         },
       
   473         /**
       
   474         * @method syncActiveShims
       
   475         * @description This method will sync the position of the shims on the Drop Targets that are currently active.
       
   476         * @param {Boolean} force Resize/sync all Targets.
       
   477         */
       
   478         syncActiveShims: function(force) {
       
   479             Y.later(0, this, function(force) {
       
   480                 var drops = ((force) ? this.targets : this._lookup());
       
   481                 Y.each(drops, function(v, k) {
       
   482                     v.sizeShim.call(v);
       
   483                 }, this);
       
   484             }, force);
       
   485         },
       
   486         /**
       
   487         * @private
       
   488         * @property mode
       
   489         * @description The mode that the drag operations will run in 0 for Point, 1 for Intersect, 2 for Strict
       
   490         * @type Number
       
   491         */
       
   492         mode: 0,
       
   493         /**
       
   494         * @private
       
   495         * @property POINT
       
   496         * @description In point mode, a Drop is targeted by the cursor being over the Target
       
   497         * @type Number
       
   498         */
       
   499         POINT: 0,
       
   500         /**
       
   501         * @private
       
   502         * @property INTERSECT
       
   503         * @description In intersect mode, a Drop is targeted by "part" of the drag node being over the Target
       
   504         * @type Number
       
   505         */
       
   506         INTERSECT: 1,
       
   507         /**
       
   508         * @private
       
   509         * @property STRICT
       
   510         * @description In strict mode, a Drop is targeted by the "entire" drag node being over the Target
       
   511         * @type Number
       
   512         */
       
   513         STRICT: 2,
       
   514         /**
       
   515         * @property useHash
       
   516         * @description Should we only check targets that are in the viewport on drags (for performance), default: true
       
   517         * @type {Boolean}
       
   518         */
       
   519         useHash: true,
       
   520         /**
       
   521         * @property activeDrop
       
   522         * @description A reference to the active Drop Target
       
   523         * @type {Object}
       
   524         */
       
   525         activeDrop: null,
       
   526         /**
       
   527         * @property validDrops
       
   528         * @description An array of the valid Drop Targets for this interaction.
       
   529         * @type {Array}
       
   530         */
       
   531         //TODO Change array/object literals to be in sync..
       
   532         validDrops: [],
       
   533         /**
       
   534         * @property otherDrops
       
   535         * @description An object literal of Other Drop Targets that we encountered during this interaction (in the case of overlapping Drop Targets)
       
   536         * @type {Object}
       
   537         */
       
   538         otherDrops: {},
       
   539         /**
       
   540         * @property targets
       
   541         * @description All of the Targets
       
   542         * @type {Array}
       
   543         */
       
   544         targets: [],
       
   545         /**
       
   546         * @private 
       
   547         * @method _addValid
       
   548         * @description Add a Drop Target to the list of Valid Targets. This list get's regenerated on each new drag operation.
       
   549         * @param {Object} drop
       
   550         * @return {Self}
       
   551         * @chainable
       
   552         */
       
   553         _addValid: function(drop) {
       
   554             this.validDrops[this.validDrops.length] = drop;
       
   555             return this;
       
   556         },
       
   557         /**
       
   558         * @private 
       
   559         * @method _removeValid
       
   560         * @description Removes a Drop Target from the list of Valid Targets. This list get's regenerated on each new drag operation.
       
   561         * @param {Object} drop
       
   562         * @return {Self}
       
   563         * @chainable
       
   564         */
       
   565         _removeValid: function(drop) {
       
   566             var drops = [];
       
   567             Y.each(this.validDrops, function(v, k) {
       
   568                 if (v !== drop) {
       
   569                     drops[drops.length] = v;
       
   570                 }
       
   571             });
       
   572 
       
   573             this.validDrops = drops;
       
   574             return this;
       
   575         },
       
   576         /**
       
   577         * @method isOverTarget
       
   578         * @description Check to see if the Drag element is over the target, method varies on current mode
       
   579         * @param {Object} drop The drop to check against
       
   580         * @return {Boolean}
       
   581         */
       
   582         isOverTarget: function(drop) {
       
   583             if (this.activeDrag && drop) {
       
   584                 var xy = this.activeDrag.mouseXY;
       
   585                 if (xy) {
       
   586                     if (this.activeDrag.get('dragMode') == this.STRICT) {
       
   587                         return this.activeDrag.get('dragNode').inRegion(drop.region, true, this.activeDrag.region);
       
   588                     } else {
       
   589                         if (drop && drop.shim) {
       
   590                             return drop.shim.intersect({
       
   591                                 top: xy[1],
       
   592                                 bottom: xy[1],
       
   593                                 left: xy[0], 
       
   594                                 right: xy[0]
       
   595                             }, drop.region).inRegion;
       
   596                         } else {
       
   597                             return false;
       
   598                         }
       
   599                     }
       
   600                 } else {
       
   601                     return false;
       
   602                 }
       
   603             } else {
       
   604                 return false;
       
   605             }
       
   606         },
       
   607         /**
       
   608         * @method clearCache
       
   609         * @description Clears the cache data used for this interaction.
       
   610         */
       
   611         clearCache: function() {
       
   612             this.validDrops = [];
       
   613             this.otherDrops = {};
       
   614             this._activeShims = [];
       
   615         },
       
   616         /**
       
   617         * @private
       
   618         * @method _activateTargets
       
   619         * @description Clear the cache and activate the shims of all the targets
       
   620         */
       
   621         _activateTargets: function() {
       
   622             this.clearCache();
       
   623             Y.each(this.targets, function(v, k) {
       
   624                 v._activateShim.apply(v, []);
       
   625             }, this);
       
   626             this._handleTargetOver();
       
   627             
       
   628         },
       
   629         /**
       
   630         * @method getBestMatch
       
   631         * @description This method will gather the area for all potential targets and see which has the hightest covered area and return it.
       
   632         * @param {Array} drops An Array of drops to scan for the best match.
       
   633         * @param {Boolean} all If present, it returns an Array. First item is best match, second is an Array of the other items in the original Array.
       
   634         * @return {Object or Array} 
       
   635         */
       
   636         getBestMatch: function(drops, all) {
       
   637             var biggest = null, area = 0, out;
       
   638             
       
   639             Y.each(drops, function(v, k) {
       
   640                 var inter = this.activeDrag.get('dragNode').intersect(v.get('node'));
       
   641                 v.region.area = inter.area;
       
   642 
       
   643                 if (inter.inRegion) {
       
   644                     if (inter.area > area) {
       
   645                         area = inter.area;
       
   646                         biggest = v;
       
   647                     }
       
   648                 }
       
   649             }, this);
       
   650             if (all) {
       
   651                 out = [];
       
   652                 //TODO Sort the others in numeric order by area covered..
       
   653                 Y.each(drops, function(v, k) {
       
   654                     if (v !== biggest) {
       
   655                         out[out.length] = v;
       
   656                     }
       
   657                 }, this);
       
   658                 return [biggest, out];
       
   659             } else {
       
   660                 return biggest;
       
   661             }
       
   662         },
       
   663         /**
       
   664         * @private
       
   665         * @method _deactivateTargets
       
   666         * @description This method fires the drop:hit, drag:drophit, drag:dropmiss methods and deactivates the shims..
       
   667         */
       
   668         _deactivateTargets: function() {
       
   669             var other = [], tmp,
       
   670                 activeDrag = this.activeDrag,
       
   671                 activeDrop = this.activeDrop;
       
   672             
       
   673             //TODO why is this check so hard??
       
   674             if (activeDrag && activeDrop && this.otherDrops[activeDrop]) {
       
   675                 if (!activeDrag.get('dragMode')) {
       
   676                     //TODO otherDrops -- private..
       
   677                     other = this.otherDrops;
       
   678                     delete other[activeDrop];
       
   679                 } else {
       
   680                     tmp = this.getBestMatch(this.otherDrops, true);
       
   681                     activeDrop = tmp[0];
       
   682                     other = tmp[1];
       
   683                 }
       
   684                 activeDrag.get('node').removeClass(this.CSS_PREFIX + '-drag-over');
       
   685                 if (activeDrop) {
       
   686                     activeDrop.fire('drop:hit', { drag: activeDrag, drop: activeDrop, others: other });
       
   687                     activeDrag.fire('drag:drophit', { drag: activeDrag,  drop: activeDrop, others: other });
       
   688                 }
       
   689             } else if (activeDrag) {
       
   690                 activeDrag.get('node').removeClass(this.CSS_PREFIX + '-drag-over');
       
   691                 activeDrag.fire('drag:dropmiss', { pageX: activeDrag.lastXY[0], pageY: activeDrag.lastXY[1] });
       
   692             } else {
       
   693             }
       
   694             
       
   695             this.activeDrop = null;
       
   696 
       
   697             Y.each(this.targets, function(v, k) {
       
   698                 v._deactivateShim.apply(v, []);
       
   699             }, this);
       
   700         },
       
   701         /**
       
   702         * @private
       
   703         * @method _dropMove
       
   704         * @description This method is called when the move method is called on the Drag Object.
       
   705         */
       
   706         _dropMove: function() {
       
   707             if (this._hasActiveShim()) {
       
   708                 this._handleTargetOver();
       
   709             } else {
       
   710                 Y.each(this.otherDrops, function(v, k) {
       
   711                     v._handleOut.apply(v, []);
       
   712                 });
       
   713             }
       
   714         },
       
   715         /**
       
   716         * @private
       
   717         * @method _lookup
       
   718         * @description Filters the list of Drops down to those in the viewport.
       
   719         * @return {Array} The valid Drop Targets that are in the viewport.
       
   720         */
       
   721         _lookup: function() {
       
   722             if (!this.useHash || this._noShim) {
       
   723                 return this.validDrops;
       
   724             }
       
   725             var drops = [];
       
   726             //Only scan drop shims that are in the Viewport
       
   727             Y.each(this.validDrops, function(v, k) {
       
   728                 if (v.shim && v.shim.inViewportRegion(false, v.region)) {
       
   729                     drops[drops.length] = v;
       
   730                 }
       
   731             });
       
   732             return drops;
       
   733                 
       
   734         },
       
   735         /**
       
   736         * @private
       
   737         * @method _handleTargetOver
       
   738         * @description This method execs _handleTargetOver on all valid Drop Targets
       
   739         */
       
   740         _handleTargetOver: function() {
       
   741             var drops = this._lookup();
       
   742             Y.each(drops, function(v, k) {
       
   743                 v._handleTargetOver.call(v);
       
   744             }, this);
       
   745         },
       
   746         /**
       
   747         * @private
       
   748         * @method _regTarget
       
   749         * @description Add the passed in Target to the targets collection
       
   750         * @param {Object} t The Target to add to the targets collection
       
   751         */
       
   752         _regTarget: function(t) {
       
   753             this.targets[this.targets.length] = t;
       
   754         },
       
   755         /**
       
   756         * @private
       
   757         * @method _unregTarget
       
   758         * @description Remove the passed in Target from the targets collection
       
   759         * @param {Object} drop The Target to remove from the targets collection
       
   760         */
       
   761         _unregTarget: function(drop) {
       
   762             var targets = [], vdrops;
       
   763             Y.each(this.targets, function(v, k) {
       
   764                 if (v != drop) {
       
   765                     targets[targets.length] = v;
       
   766                 }
       
   767             }, this);
       
   768             this.targets = targets;
       
   769 
       
   770             vdrops = [];
       
   771             Y.each(this.validDrops, function(v, k) {
       
   772                 if (v !== drop) {
       
   773                     vdrops[vdrops.length] = v;
       
   774                 }
       
   775             });
       
   776 
       
   777             this.validDrops = vdrops;
       
   778         },
       
   779         /**
       
   780         * @method getDrop
       
   781         * @description Get a valid Drop instance back from a Node or a selector string, false otherwise
       
   782         * @param {String/Object} node The Node instance or Selector string to check for a valid Drop Object
       
   783         * @return {Object}
       
   784         */
       
   785         getDrop: function(node) {
       
   786             var drop = false,
       
   787                 n = Y.Node.get(node);
       
   788             if (n instanceof Y.Node) {
       
   789                 Y.each(this.targets, function(v, k) {
       
   790                     if (n.compareTo(v.get('node'))) {
       
   791                         drop = v;
       
   792                     }
       
   793                 });
       
   794             }
       
   795             return drop;
       
   796         }
       
   797     }, true);
       
   798     
       
   799 
       
   800 
       
   801 
       
   802 
       
   803 
       
   804 
       
   805 }, '3.0.0b1' ,{requires:['dd-ddm'], skinnable:false});
       
   806 YUI.add('dd-drag', function(Y) {
       
   807 
       
   808 
       
   809     /**
       
   810      * 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.
       
   811      * @module dd
       
   812      * @submodule dd-drag
       
   813      */     
       
   814     /**
       
   815      * This class provides the ability to drag a Node.
       
   816      * @class Drag
       
   817      * @extends Base
       
   818      * @constructor
       
   819      * @namespace DD
       
   820      */
       
   821 
       
   822     var DDM = Y.DD.DDM,
       
   823         NODE = 'node',
       
   824         DRAGGING = 'dragging',
       
   825         DRAG_NODE = 'dragNode',
       
   826         OFFSET_HEIGHT = 'offsetHeight',
       
   827         OFFSET_WIDTH = 'offsetWidth',        
       
   828         MOUSE_UP = 'mouseup',
       
   829         MOUSE_DOWN = 'mousedown',
       
   830         DRAG_START = 'dragstart',
       
   831         /**
       
   832         * @event drag:mouseDown
       
   833         * @description Handles the mousedown DOM event, checks to see if you have a valid handle then starts the drag timers.
       
   834         * @preventable _defMouseDownFn
       
   835         * @param {Event.Facade} ev The mousedown event.
       
   836         * @bubbles DDM
       
   837         * @type {Event.Custom}
       
   838         */
       
   839         EV_MOUSE_DOWN = 'drag:mouseDown',
       
   840         /**
       
   841         * @event drag:afterMouseDown
       
   842         * @description Fires after the mousedown event has been cleared.
       
   843         * @param {Event.Facade} ev The mousedown event.
       
   844         * @bubbles DDM
       
   845         * @type {Event.Custom}
       
   846         */
       
   847         EV_AFTER_MOUSE_DOWN = 'drag:afterMouseDown',
       
   848         /**
       
   849         * @event drag:removeHandle
       
   850         * @description Fires after a handle is removed.
       
   851         * @bubbles DDM
       
   852         * @type {Event.Custom}
       
   853         */
       
   854         EV_REMOVE_HANDLE = 'drag:removeHandle',
       
   855         /**
       
   856         * @event drag:addHandle
       
   857         * @description Fires after a handle is added.
       
   858         * @bubbles DDM
       
   859         * @type {Event.Custom}
       
   860         */
       
   861         EV_ADD_HANDLE = 'drag:addHandle',
       
   862         /**
       
   863         * @event drag:removeInvalid
       
   864         * @description Fires after an invalid selector is removed.
       
   865         * @bubbles DDM
       
   866         * @type {Event.Custom}
       
   867         */
       
   868         EV_REMOVE_INVALID = 'drag:removeInvalid',
       
   869         /**
       
   870         * @event drag:addInvalid
       
   871         * @description Fires after an invalid selector is added.
       
   872         * @bubbles DDM
       
   873         * @type {Event.Custom}
       
   874         */
       
   875         EV_ADD_INVALID = 'drag:addInvalid',
       
   876         /**
       
   877         * @event drag:start
       
   878         * @description Fires at the start of a drag operation.
       
   879         * @bubbles DDM
       
   880         * @type {Event.Custom}
       
   881         */
       
   882         EV_START = 'drag:start',
       
   883         /**
       
   884         * @event drag:end
       
   885         * @description Fires at the end of a drag operation.
       
   886         * @bubbles DDM
       
   887         * @type {Event.Custom}
       
   888         */
       
   889         EV_END = 'drag:end',
       
   890         /**
       
   891         * @event drag:drag
       
   892         * @description Fires every mousemove during a drag operation.
       
   893         * @bubbles DDM
       
   894         * @type {Event.Custom}
       
   895         */
       
   896         EV_DRAG = 'drag:drag',
       
   897         /**
       
   898         * @event drag:align
       
   899         * @preventable _defAlignFn
       
   900         * @description Fires when this node is aligned.
       
   901         * @bubbles DDM
       
   902         * @type {Event.Custom}
       
   903         */
       
   904         EV_ALIGN = 'drag:align',
       
   905         /**
       
   906         * @event drag:over
       
   907         * @description Fires when this node is over a Drop Target. (Fired from dd-drop)
       
   908         * @bubbles DDM
       
   909         * @type {Event.Custom}
       
   910         */
       
   911         /**
       
   912         * @event drag:enter
       
   913         * @description Fires when this node enters a Drop Target. (Fired from dd-drop)
       
   914         * @bubbles DDM
       
   915         * @type {Event.Custom}
       
   916         */
       
   917         /**
       
   918         * @event drag:exit
       
   919         * @description Fires when this node exits a Drop Target. (Fired from dd-drop)
       
   920         * @bubbles DDM
       
   921         * @type {Event.Custom}
       
   922         */
       
   923         /**
       
   924         * @event drag:drophit
       
   925         * @description Fires when this node is dropped on a valid Drop Target. (Fired from dd-ddm-drop)
       
   926         * @bubbles DDM
       
   927         * @type {Event.Custom}
       
   928         */
       
   929         /**
       
   930         * @event drag:dropmiss
       
   931         * @description Fires when this node is dropped on an invalid Drop Target. (Fired from dd-ddm-drop)
       
   932         * @bubbles DDM
       
   933         * @type {Event.Custom}
       
   934         */
       
   935     
       
   936     Drag = function() {
       
   937         this._lazyAddAttrs = false;
       
   938         Drag.superclass.constructor.apply(this, arguments);
       
   939 
       
   940         DDM._regDrag(this);
       
   941     };
       
   942 
       
   943     Drag.NAME = 'drag';
       
   944 
       
   945     Drag.ATTRS = {
       
   946         /**
       
   947         * @attribute node
       
   948         * @description Y.Node instanace to use as the element to initiate a drag operation
       
   949         * @type Node
       
   950         */
       
   951         node: {
       
   952             setter: function(node) {
       
   953                 var n = Y.get(node);
       
   954                 if (!n) {
       
   955                     Y.error('DD.Drag: Invalid Node Given: ' + node);
       
   956                 } else {
       
   957                     n = n.item(0);
       
   958                 }
       
   959                 return n;
       
   960             }
       
   961         },
       
   962         /**
       
   963         * @attribute dragNode
       
   964         * @description Y.Node instanace to use as the draggable element, defaults to node
       
   965         * @type Node
       
   966         */
       
   967         dragNode: {
       
   968             setter: function(node) {
       
   969                 var n = Y.Node.get(node);
       
   970                 if (!n) {
       
   971                     Y.error('DD.Drag: Invalid dragNode Given: ' + node);
       
   972                 }
       
   973                 return n;
       
   974             }
       
   975         },
       
   976         /**
       
   977         * @attribute offsetNode
       
   978         * @description Offset the drag element by the difference in cursor position: default true
       
   979         * @type Boolean
       
   980         */
       
   981         offsetNode: {
       
   982             value: true
       
   983         },
       
   984         /**
       
   985         * @attribute clickPixelThresh
       
   986         * @description The number of pixels to move to start a drag operation, default is 3.
       
   987         * @type Number
       
   988         */
       
   989         clickPixelThresh: {
       
   990             value: DDM.get('clickPixelThresh')
       
   991         },
       
   992         /**
       
   993         * @attribute clickTimeThresh
       
   994         * @description The number of milliseconds a mousedown has to pass to start a drag operation, default is 1000.
       
   995         * @type Number
       
   996         */
       
   997         clickTimeThresh: {
       
   998             value: DDM.get('clickTimeThresh')
       
   999         },
       
  1000         /**
       
  1001         * @attribute lock
       
  1002         * @description Set to lock this drag element so that it can't be dragged: default false.
       
  1003         * @type Boolean
       
  1004         */
       
  1005         lock: {
       
  1006             value: false,
       
  1007             setter: function(lock) {
       
  1008                 if (lock) {
       
  1009                     this.get(NODE).addClass(DDM.CSS_PREFIX + '-locked');
       
  1010                 } else {
       
  1011                     this.get(NODE).removeClass(DDM.CSS_PREFIX + '-locked');
       
  1012                 }
       
  1013                 return lock;
       
  1014             }
       
  1015         },
       
  1016         /**
       
  1017         * @attribute data
       
  1018         * @description A payload holder to store arbitrary data about this drag object, can be used to store any value.
       
  1019         * @type Mixed
       
  1020         */
       
  1021         data: {
       
  1022             value: false
       
  1023         },
       
  1024         /**
       
  1025         * @attribute move
       
  1026         * @description If this is false, the drag element will not move with the cursor: default true. Can be used to "resize" the element.
       
  1027         * @type Boolean
       
  1028         */
       
  1029         move: {
       
  1030             value: true
       
  1031         },
       
  1032         /**
       
  1033         * @attribute useShim
       
  1034         * @description Use the protective shim on all drag operations: default true. Only works with dd-ddm, not dd-ddm-base.
       
  1035         * @type Boolean
       
  1036         */
       
  1037         useShim: {
       
  1038             value: true
       
  1039         },
       
  1040         /**
       
  1041         * @attribute activeHandle
       
  1042         * @description This config option is set by Drag to inform you of which handle fired the drag event (in the case that there are several handles): default false.
       
  1043         * @type Node
       
  1044         */
       
  1045         activeHandle: {
       
  1046             value: false
       
  1047         },
       
  1048         /**
       
  1049         * @attribute primaryButtonOnly
       
  1050         * @description By default a drag operation will only begin if the mousedown occurred with the primary mouse button. Setting this to false will allow for all mousedown events to trigger a drag.
       
  1051         * @type Boolean
       
  1052         */
       
  1053         primaryButtonOnly: {
       
  1054             value: true
       
  1055         },
       
  1056         /**
       
  1057         * @attribute dragging
       
  1058         * @description This attribute is not meant to be used by the implementor, it is meant to be used as an Event tracker so you can listen for it to change.
       
  1059         * @type Boolean
       
  1060         */
       
  1061         dragging: {
       
  1062             value: false
       
  1063         },
       
  1064         parent: {
       
  1065             value: false
       
  1066         },
       
  1067         /**
       
  1068         * @attribute target
       
  1069         * @description This attribute only works if the dd-drop module has been loaded. It will make this node a drop target as well as draggable.
       
  1070         * @type Boolean
       
  1071         */
       
  1072         target: {
       
  1073             value: false,
       
  1074             setter: function(config) {
       
  1075                 this._handleTarget(config);
       
  1076                 return config;
       
  1077             }
       
  1078         },
       
  1079         /**
       
  1080         * @attribute dragMode
       
  1081         * @description This attribute only works if the dd-drop module is active. It will set the dragMode (point, intersect, strict) of this Drag instance.
       
  1082         * @type String
       
  1083         */
       
  1084         dragMode: {
       
  1085             value: null,
       
  1086             setter: function(mode) {
       
  1087                 return DDM._setDragMode(mode);
       
  1088             }
       
  1089         },
       
  1090         /**
       
  1091         * @attribute groups
       
  1092         * @description Array of groups to add this drag into.
       
  1093         * @type Array
       
  1094         */
       
  1095         groups: {
       
  1096             value: ['default'],
       
  1097             getter: function() {
       
  1098                 if (!this._groups) {
       
  1099                     this._groups = {};
       
  1100                 }
       
  1101                 var ret = [];
       
  1102                 Y.each(this._groups, function(v, k) {
       
  1103                     ret[ret.length] = k;
       
  1104                 });
       
  1105                 return ret;
       
  1106             },
       
  1107             setter: function(g) {
       
  1108                 this._groups = {};
       
  1109                 Y.each(g, function(v, k) {
       
  1110                     this._groups[v] = true;
       
  1111                 }, this);
       
  1112                 return g;
       
  1113             }
       
  1114         },
       
  1115         /**
       
  1116         * @attribute handles
       
  1117         * @description Array of valid handles to add. Adding something here will set all handles, even if previously added with addHandle
       
  1118         * @type Array
       
  1119         */
       
  1120         handles: {
       
  1121             value: null,
       
  1122             setter: function(g) {
       
  1123                 if (g) {
       
  1124                     this._handles = {};
       
  1125                     Y.each(g, function(v, k) {
       
  1126                         this._handles[v] = true;
       
  1127                     }, this);
       
  1128                 } else {
       
  1129                     this._handles = null;
       
  1130                 }
       
  1131                 return g;
       
  1132             }
       
  1133         },
       
  1134         /**
       
  1135         * @attribute bubbles
       
  1136         * @description Controls the default bubble parent for this Drag instance. Default: Y.DD.DDM. Set to false to disable bubbling.
       
  1137         * @type Object
       
  1138         */
       
  1139         bubbles: {
       
  1140             writeOnce: true,
       
  1141             value: Y.DD.DDM
       
  1142         }
       
  1143     };
       
  1144 
       
  1145     Y.extend(Drag, Y.Base, {
       
  1146         /**
       
  1147         * @method addToGroup
       
  1148         * @description Add this Drag instance to a group, this should be used for on-the-fly group additions.
       
  1149         * @param {String} g The group to add this Drag Instance to.
       
  1150         * @return {Self}
       
  1151         * @chainable
       
  1152         */
       
  1153         addToGroup: function(g) {
       
  1154             this._groups[g] = true;
       
  1155             DDM._activateTargets();
       
  1156             return this;
       
  1157         },
       
  1158         /**
       
  1159         * @method removeFromGroup
       
  1160         * @description Remove this Drag instance from a group, this should be used for on-the-fly group removals.
       
  1161         * @param {String} g The group to remove this Drag Instance from.
       
  1162         * @return {Self}
       
  1163         * @chainable
       
  1164         */
       
  1165         removeFromGroup: function(g) {
       
  1166             delete this._groups[g];
       
  1167             DDM._activateTargets();
       
  1168             return this;
       
  1169         },
       
  1170         /**
       
  1171         * @property target
       
  1172         * @description This will be a reference to the Drop instance associated with this drag if the target: true config attribute is set..
       
  1173         * @type {Object}
       
  1174         */
       
  1175         target: null,
       
  1176         /**
       
  1177         * @private
       
  1178         * @method _handleTarget
       
  1179         * @description Attribute handler for the target config attribute.
       
  1180         * @param {Boolean/Object}
       
  1181         * @return {Boolean/Object}
       
  1182         */
       
  1183         _handleTarget: function(config) {
       
  1184             if (Y.DD.Drop) {
       
  1185                 if (config === false) {
       
  1186                     if (this.target) {
       
  1187                         DDM._unregTarget(this.target);
       
  1188                         this.target = null;
       
  1189                     }
       
  1190                     return false;
       
  1191                 } else {
       
  1192                     if (!Y.Lang.isObject(config)) {
       
  1193                         config = {};
       
  1194                     }
       
  1195                     config.bubbles = ('bubbles' in config) ? config.bubbles : this.get('bubbles');
       
  1196                     config.node = this.get(NODE);
       
  1197                     config.groups = config.groups || this.get('groups');
       
  1198                     this.target = new Y.DD.Drop(config);
       
  1199                 }
       
  1200             } else {
       
  1201                 return false;
       
  1202             }
       
  1203         },
       
  1204         /**
       
  1205         * @private
       
  1206         * @property _groups
       
  1207         * @description Storage Array for the groups this drag belongs to.
       
  1208         * @type {Array}
       
  1209         */
       
  1210         _groups: null,
       
  1211         /**
       
  1212         * @private
       
  1213         * @method _createEvents
       
  1214         * @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
       
  1215         */
       
  1216         _createEvents: function() {
       
  1217             
       
  1218             this.publish(EV_MOUSE_DOWN, {
       
  1219                 defaultFn: this._defMouseDownFn,
       
  1220                 queuable: false,
       
  1221                 emitFacade: true,
       
  1222                 bubbles: true,
       
  1223                 prefix: 'drag'
       
  1224             });
       
  1225             
       
  1226             this.publish(EV_ALIGN, {
       
  1227                 defaultFn: this._defAlignFn,
       
  1228                 queuable: false,
       
  1229                 emitFacade: true,
       
  1230                 bubbles: true,
       
  1231                 prefix: 'drag'
       
  1232             });
       
  1233             
       
  1234             this.publish(EV_DRAG, {
       
  1235                 defaultFn: this._defDragFn,
       
  1236                 queuable: false,
       
  1237                 emitFacade: true,
       
  1238                 bubbles: true,
       
  1239                 prefix: 'drag'
       
  1240             });
       
  1241             
       
  1242             this.publish(EV_END, {
       
  1243                 preventedFn: this._prevEndFn,
       
  1244                 queuable: false,
       
  1245                 emitFacade: true,
       
  1246                 bubbles: true,
       
  1247                 prefix: 'drag'
       
  1248             });
       
  1249             
       
  1250             var ev = [
       
  1251                 EV_AFTER_MOUSE_DOWN,
       
  1252                 EV_REMOVE_HANDLE,
       
  1253                 EV_ADD_HANDLE,
       
  1254                 EV_REMOVE_INVALID,
       
  1255                 EV_ADD_INVALID,
       
  1256                 EV_START,
       
  1257                 'drag:drophit',
       
  1258                 'drag:dropmiss',
       
  1259                 'drag:over',
       
  1260                 'drag:enter',
       
  1261                 'drag:exit'
       
  1262             ];
       
  1263             
       
  1264             Y.each(ev, function(v, k) {
       
  1265                 this.publish(v, {
       
  1266                     type: v,
       
  1267                     emitFacade: true,
       
  1268                     bubbles: true,
       
  1269                     preventable: false,
       
  1270                     queuable: false,
       
  1271                     prefix: 'drag'
       
  1272                 });
       
  1273             }, this);
       
  1274 
       
  1275             if (this.get('bubbles')) {
       
  1276                 this.addTarget(this.get('bubbles'));
       
  1277             }
       
  1278             
       
  1279            
       
  1280         },
       
  1281         /**
       
  1282         * @private
       
  1283         * @property _ev_md
       
  1284         * @description A private reference to the mousedown DOM event
       
  1285         * @type {Event.Facade}
       
  1286         */
       
  1287         _ev_md: null,
       
  1288         /**
       
  1289         * @private
       
  1290         * @property _startTime
       
  1291         * @description The getTime of the mousedown event. Not used, just here in case someone wants/needs to use it.
       
  1292         * @type Date
       
  1293         */
       
  1294         _startTime: null,
       
  1295         /**
       
  1296         * @private
       
  1297         * @property _endTime
       
  1298         * @description The getTime of the mouseup event. Not used, just here in case someone wants/needs to use it.
       
  1299         * @type Date
       
  1300         */
       
  1301         _endTime: null,
       
  1302         /**
       
  1303         * @private
       
  1304         * @property _handles
       
  1305         * @description A private hash of the valid drag handles
       
  1306         * @type {Object}
       
  1307         */
       
  1308         _handles: null,
       
  1309         /**
       
  1310         * @private
       
  1311         * @property _invalids
       
  1312         * @description A private hash of the invalid selector strings
       
  1313         * @type {Object}
       
  1314         */
       
  1315         _invalids: null,
       
  1316         /**
       
  1317         * @private
       
  1318         * @property _invalidsDefault
       
  1319         * @description A private hash of the default invalid selector strings: {'textarea': true, 'input': true, 'a': true, 'button': true}
       
  1320         * @type {Object}
       
  1321         */
       
  1322         _invalidsDefault: {'textarea': true, 'input': true, 'a': true, 'button': true},
       
  1323         /**
       
  1324         * @private
       
  1325         * @property _dragThreshMet
       
  1326         * @description Private flag to see if the drag threshhold was met
       
  1327         * @type {Boolean}
       
  1328         */
       
  1329         _dragThreshMet: null,
       
  1330         /**
       
  1331         * @private
       
  1332         * @property _fromTimeout
       
  1333         * @description Flag to determine if the drag operation came from a timeout
       
  1334         * @type {Boolean}
       
  1335         */
       
  1336         _fromTimeout: null,
       
  1337         /**
       
  1338         * @private
       
  1339         * @property _clickTimeout
       
  1340         * @description Holder for the setTimeout call
       
  1341         * @type {Boolean}
       
  1342         */
       
  1343         _clickTimeout: null,
       
  1344         /**
       
  1345         * @property deltaXY
       
  1346         * @description The offset of the mouse position to the element's position
       
  1347         * @type {Array}
       
  1348         */
       
  1349         deltaXY: null,
       
  1350         /**
       
  1351         * @property startXY
       
  1352         * @description The initial mouse position
       
  1353         * @type {Array}
       
  1354         */
       
  1355         startXY: null,
       
  1356         /**
       
  1357         * @property nodeXY
       
  1358         * @description The initial element position
       
  1359         * @type {Array}
       
  1360         */
       
  1361         nodeXY: null,
       
  1362         /**
       
  1363         * @property lastXY
       
  1364         * @description The position of the element as it's moving (for offset calculations)
       
  1365         * @type {Array}
       
  1366         */
       
  1367         lastXY: null,
       
  1368         /**
       
  1369         * @property actXY
       
  1370         * @description The xy that the node will be set to. Changing this will alter the position as it's dragged.
       
  1371         * @type {Array}
       
  1372         */
       
  1373         actXY: null,
       
  1374         /**
       
  1375         * @property realXY
       
  1376         * @description The real xy position of the node.
       
  1377         * @type {Array}
       
  1378         */
       
  1379         realXY: null,
       
  1380         /**
       
  1381         * @property mouseXY
       
  1382         * @description The XY coords of the mousemove
       
  1383         * @type {Array}
       
  1384         */
       
  1385         mouseXY: null,
       
  1386         /**
       
  1387         * @property region
       
  1388         * @description A region object associated with this drag, used for checking regions while dragging.
       
  1389         * @type Object
       
  1390         */
       
  1391         region: null,       
       
  1392         /**
       
  1393         * @private
       
  1394         * @method _handleMouseUp
       
  1395         * @description Handler for the mouseup DOM event
       
  1396         * @param {Event.Facade}
       
  1397         */
       
  1398         _handleMouseUp: function(ev) {
       
  1399             this._fixIEMouseUp();
       
  1400             if (DDM.activeDrag) {
       
  1401                 DDM._end();
       
  1402             }
       
  1403         },
       
  1404         /** 
       
  1405         * @private
       
  1406         * @method _fixDragStart
       
  1407         * @description The function we use as the ondragstart handler when we start a drag in Internet Explorer. This keeps IE from blowing up on images as drag handles.
       
  1408         */
       
  1409         _fixDragStart: function(e) {
       
  1410             e.preventDefault();
       
  1411         },
       
  1412         /** 
       
  1413         * @private
       
  1414         * @method _ieSelectFix
       
  1415         * @description The function we use as the onselectstart handler when we start a drag in Internet Explorer
       
  1416         */
       
  1417         _ieSelectFix: function() {
       
  1418             return false;
       
  1419         },
       
  1420         /** 
       
  1421         * @private
       
  1422         * @property _ieSelectBack
       
  1423         * @description We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it.
       
  1424         */
       
  1425         _ieSelectBack: null,
       
  1426         /**
       
  1427         * @private
       
  1428         * @method _fixIEMouseDown
       
  1429         * @description This method copies the onselectstart listner on the document to the _ieSelectFix property
       
  1430         */
       
  1431         _fixIEMouseDown: function() {
       
  1432             if (Y.UA.ie) {
       
  1433                 this._ieSelectBack = Y.config.doc.body.onselectstart;
       
  1434                 Y.config.doc.body.onselectstart = this._ieSelectFix;
       
  1435             }           
       
  1436         },
       
  1437         /**
       
  1438         * @private
       
  1439         * @method _fixIEMouseUp
       
  1440         * @description This method copies the _ieSelectFix property back to the onselectstart listner on the document.
       
  1441         */
       
  1442         _fixIEMouseUp: function() {
       
  1443             if (Y.UA.ie) {
       
  1444                 Y.config.doc.body.onselectstart = this._ieSelectBack;
       
  1445             }           
       
  1446         },
       
  1447         /**
       
  1448         * @private
       
  1449         * @method _handleMouseDownEvent
       
  1450         * @description Handler for the mousedown DOM event
       
  1451         * @param {Event.Facade}
       
  1452         */
       
  1453         _handleMouseDownEvent: function(ev) {
       
  1454             this.fire(EV_MOUSE_DOWN, { ev: ev });
       
  1455         },
       
  1456         /**
       
  1457         * @private
       
  1458         * @method _defMouseDownFn
       
  1459         * @description Handler for the mousedown DOM event
       
  1460         * @param {Event.Facade}
       
  1461         */
       
  1462         _defMouseDownFn: function(e) {
       
  1463             var ev = e.ev;
       
  1464             this._dragThreshMet = false;
       
  1465             this._ev_md = ev;
       
  1466             
       
  1467             if (this.get('primaryButtonOnly') && ev.button > 1) {
       
  1468                 return false;
       
  1469             }
       
  1470             if (this.validClick(ev)) {
       
  1471                 this._fixIEMouseDown();
       
  1472                 ev.halt();
       
  1473                 this._setStartPosition([ev.pageX, ev.pageY]);
       
  1474 
       
  1475                 DDM.activeDrag = this;
       
  1476                 
       
  1477                 this._clickTimeout = Y.later(this.get('clickTimeThresh'), this, this._timeoutCheck);
       
  1478             }
       
  1479             this.fire(EV_AFTER_MOUSE_DOWN, { ev: ev });
       
  1480         },
       
  1481         /**
       
  1482         * @method validClick
       
  1483         * @description Method first checks to see if we have handles, if so it validates the click against the handle. Then if it finds a valid handle, it checks it against the invalid handles list. Returns true if a good handle was used, false otherwise.
       
  1484         * @param {Event.Facade}
       
  1485         * @return {Boolean}
       
  1486         */
       
  1487         validClick: function(ev) {
       
  1488             var r = false, n = false,
       
  1489             tar = ev.target,
       
  1490             hTest = null,
       
  1491             els = null,
       
  1492             set = false;
       
  1493             if (this._handles) {
       
  1494                 Y.each(this._handles, function(i, n) {
       
  1495                     if (Y.Lang.isString(n)) {
       
  1496                         //Am I this or am I inside this
       
  1497                         if (tar.test(n + ', ' + n + ' *') && !hTest) {
       
  1498                             hTest = n;
       
  1499                             r = true;
       
  1500                         }
       
  1501                     }
       
  1502                 });
       
  1503             } else {
       
  1504                 n = this.get(NODE)
       
  1505                 if (n.contains(tar) || n.compareTo(tar)) {
       
  1506                     r = true;
       
  1507                 }
       
  1508             }
       
  1509             if (r) {
       
  1510                 if (this._invalids) {
       
  1511                     Y.each(this._invalids, function(i, n) {
       
  1512                         if (Y.Lang.isString(n)) {
       
  1513                             //Am I this or am I inside this
       
  1514                             if (tar.test(n + ', ' + n + ' *')) {
       
  1515                                 r = false;
       
  1516                             }
       
  1517                         }
       
  1518                     });
       
  1519                 }
       
  1520             }
       
  1521             if (r) {
       
  1522                 if (hTest) {
       
  1523                     els = ev.currentTarget.queryAll(hTest);
       
  1524                     set = false;
       
  1525                     els.each(function(n, i) {
       
  1526                         if ((n.contains(tar) || n.compareTo(tar)) && !set) {
       
  1527                             set = true;
       
  1528                             this.set('activeHandle', n);
       
  1529                         }
       
  1530                     }, this);
       
  1531                 } else {
       
  1532                     this.set('activeHandle', this.get(NODE));
       
  1533                 }
       
  1534             }
       
  1535             return r;
       
  1536         },
       
  1537         /**
       
  1538         * @private
       
  1539         * @method _setStartPosition
       
  1540         * @description Sets the current position of the Element and calculates the offset
       
  1541         * @param {Array} xy The XY coords to set the position to.
       
  1542         */
       
  1543         _setStartPosition: function(xy) {
       
  1544             this.startXY = xy;
       
  1545             
       
  1546             this.nodeXY = this.lastXY = this.realXY = this.get(NODE).getXY();
       
  1547 
       
  1548             if (this.get('offsetNode')) {
       
  1549                 this.deltaXY = [(this.startXY[0] - this.nodeXY[0]), (this.startXY[1] - this.nodeXY[1])];
       
  1550             } else {
       
  1551                 this.deltaXY = [0, 0];
       
  1552             }
       
  1553         },
       
  1554         /**
       
  1555         * @private
       
  1556         * @method _timeoutCheck
       
  1557         * @description The method passed to setTimeout to determine if the clickTimeThreshold was met.
       
  1558         */
       
  1559         _timeoutCheck: function() {
       
  1560             if (!this.get('lock') && !this._dragThreshMet) {
       
  1561                 this._fromTimeout = this._dragThreshMet = true;
       
  1562                 this.start();
       
  1563                 this._alignNode([this._ev_md.pageX, this._ev_md.pageY], true);
       
  1564             }
       
  1565         },
       
  1566         /**
       
  1567         * @method removeHandle
       
  1568         * @description Remove a Selector added by addHandle
       
  1569         * @param {String} str The selector for the handle to be removed. 
       
  1570         * @return {Self}
       
  1571         * @chainable
       
  1572         */
       
  1573         removeHandle: function(str) {
       
  1574             if (this._handles[str]) {
       
  1575                 delete this._handles[str];
       
  1576                 this.fire(EV_REMOVE_HANDLE, { handle: str });
       
  1577             }
       
  1578             return this;
       
  1579         },
       
  1580         /**
       
  1581         * @method addHandle
       
  1582         * @description Add a handle to a drag element. Drag only initiates when a mousedown happens on this element.
       
  1583         * @param {String} str The selector to test for a valid handle. Must be a child of the element.
       
  1584         * @return {Self}
       
  1585         * @chainable
       
  1586         */
       
  1587         addHandle: function(str) {
       
  1588             if (!this._handles) {
       
  1589                 this._handles = {};
       
  1590             }
       
  1591             if (Y.Lang.isString(str)) {
       
  1592                 this._handles[str] = true;
       
  1593                 this.fire(EV_ADD_HANDLE, { handle: str });
       
  1594             }
       
  1595             return this;
       
  1596         },
       
  1597         /**
       
  1598         * @method removeInvalid
       
  1599         * @description Remove an invalid handle added by addInvalid
       
  1600         * @param {String} str The invalid handle to remove from the internal list.
       
  1601         * @return {Self}
       
  1602         * @chainable
       
  1603         */
       
  1604         removeInvalid: function(str) {
       
  1605             if (this._invalids[str]) {
       
  1606                 this._invalids[str] = null;
       
  1607                 delete this._invalids[str];
       
  1608                 this.fire(EV_REMOVE_INVALID, { handle: str });
       
  1609             }
       
  1610             return this;
       
  1611         },
       
  1612         /**
       
  1613         * @method addInvalid
       
  1614         * @description Add a selector string to test the handle against. If the test passes the drag operation will not continue.
       
  1615         * @param {String} str The selector to test against to determine if this is an invalid drag handle.
       
  1616         * @return {Self}
       
  1617         * @chainable
       
  1618         */
       
  1619         addInvalid: function(str) {
       
  1620             if (Y.Lang.isString(str)) {
       
  1621                 this._invalids[str] = true;
       
  1622                 this.fire(EV_ADD_INVALID, { handle: str });
       
  1623             }
       
  1624             return this;
       
  1625         },
       
  1626         /**
       
  1627         * @private
       
  1628         * @method initializer
       
  1629         * @description Internal init handler
       
  1630         */
       
  1631         initializer: function() {
       
  1632             this.get(NODE).dd = this;
       
  1633 
       
  1634             if (!this.get(NODE).get('id')) {
       
  1635                 var id = Y.stamp(this.get(NODE));
       
  1636                 this.get(NODE).set('id', id);
       
  1637             }
       
  1638 
       
  1639             this.actXY = [];
       
  1640             
       
  1641             this._invalids = Y.clone(this._invalidsDefault, true);
       
  1642 
       
  1643             this._createEvents();
       
  1644             
       
  1645             if (!this.get(DRAG_NODE)) {
       
  1646                 this.set(DRAG_NODE, this.get(NODE));
       
  1647             }
       
  1648             this._prep();
       
  1649             this._dragThreshMet = false;
       
  1650             //Shouldn't have to do this..
       
  1651             this.set('groups', this.get('groups'));
       
  1652         },
       
  1653         /**
       
  1654         * @private
       
  1655         * @method _prep
       
  1656         * @description Attach event listners and add classname
       
  1657         */
       
  1658         _prep: function() {
       
  1659             var node = this.get(NODE);
       
  1660             node.addClass(DDM.CSS_PREFIX + '-draggable');
       
  1661             node.on(MOUSE_DOWN, Y.bind(this._handleMouseDownEvent, this));
       
  1662             node.on(MOUSE_UP, Y.bind(this._handleMouseUp, this));
       
  1663             node.on(DRAG_START, Y.bind(this._fixDragStart, this));
       
  1664         },
       
  1665         /**
       
  1666         * @private
       
  1667         * @method _unprep
       
  1668         * @description Detach event listeners and remove classname
       
  1669         */
       
  1670         _unprep: function() {
       
  1671             var node = this.get(NODE);
       
  1672             node.removeClass(DDM.CSS_PREFIX + '-draggable');
       
  1673             node.detachAll();
       
  1674         },
       
  1675         /**
       
  1676         * @method start
       
  1677         * @description Starts the drag operation
       
  1678         * @return {Self}
       
  1679         * @chainable
       
  1680         */
       
  1681         start: function() {
       
  1682             if (!this.get('lock') && !this.get(DRAGGING)) {
       
  1683                 var node = this.get(NODE), ow = node.get(OFFSET_WIDTH), oh = node.get(OFFSET_HEIGHT);
       
  1684                 this._startTime = (new Date()).getTime();
       
  1685 
       
  1686                 DDM._start(this.deltaXY, [oh, ow]);
       
  1687                 node.addClass(DDM.CSS_PREFIX + '-dragging');
       
  1688                 this.fire(EV_START, {
       
  1689                     pageX: this.nodeXY[0],
       
  1690                     pageY: this.nodeXY[1],
       
  1691                     startTime: this._startTime
       
  1692                 });
       
  1693                 var xy = this.nodeXY;
       
  1694 
       
  1695                 
       
  1696                 this.region = {
       
  1697                     '0': xy[0], 
       
  1698                     '1': xy[1],
       
  1699                     area: 0,
       
  1700                     top: xy[1],
       
  1701                     right: xy[0] + ow,
       
  1702                     bottom: xy[1] + oh,
       
  1703                     left: xy[0]
       
  1704                 };
       
  1705                 this.set(DRAGGING, true);
       
  1706             }
       
  1707             return this;
       
  1708         },
       
  1709         /**
       
  1710         * @method end
       
  1711         * @description Ends the drag operation
       
  1712         * @return {Self}
       
  1713         * @chainable
       
  1714         */
       
  1715         end: function() {
       
  1716             this._endTime = (new Date()).getTime();
       
  1717             if (this._clickTimeout) {
       
  1718                 this._clickTimeout.cancel();
       
  1719             }
       
  1720             this._dragThreshMet = false;
       
  1721             this._fromTimeout = false;
       
  1722             if (!this.get('lock') && this.get(DRAGGING)) {
       
  1723                 this.fire(EV_END, {
       
  1724                     pageX: this.lastXY[0],
       
  1725                     pageY: this.lastXY[1],
       
  1726                     startTime: this._startTime,
       
  1727                     endTime: this._endTime
       
  1728                 });
       
  1729             }
       
  1730             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-dragging');
       
  1731             this.set(DRAGGING, false);
       
  1732             this.deltaXY = [0, 0];
       
  1733 
       
  1734             return this;
       
  1735         },
       
  1736         /**
       
  1737         * @private
       
  1738         * @method _prevEndFn
       
  1739         * @description Handler for preventing the drag:end event. It will reset the node back to it's start position
       
  1740         */
       
  1741         _prevEndFn: function(e) {
       
  1742             //Bug #1852577
       
  1743             this.get(DRAG_NODE).setXY(this.nodeXY);
       
  1744         },
       
  1745         /**
       
  1746         * @private
       
  1747         * @method _align
       
  1748         * @description Calculates the offsets and set's the XY that the element will move to.
       
  1749         * @param {Array} xy The xy coords to align with.
       
  1750         */
       
  1751         _align: function(xy) {
       
  1752             this.fire(EV_ALIGN, {pageX: xy[0], pageY: xy[1] });
       
  1753         },
       
  1754         /**
       
  1755         * @private
       
  1756         * @method _defAlignFn
       
  1757         * @description Calculates the offsets and set's the XY that the element will move to.
       
  1758         * @param {Event.Facade} e The drag:align event.
       
  1759         */
       
  1760         _defAlignFn: function(e) {
       
  1761             this.actXY = [e.pageX - this.deltaXY[0], e.pageY - this.deltaXY[1]];
       
  1762         },
       
  1763         /**
       
  1764         * @private
       
  1765         * @method _alignNode
       
  1766         * @description This method performs the alignment before the element move.
       
  1767         * @param {Array} eXY The XY to move the element to, usually comes from the mousemove DOM event.
       
  1768         */
       
  1769         _alignNode: function(eXY) {
       
  1770             this._align(eXY);
       
  1771             this._moveNode();
       
  1772         },
       
  1773         /**
       
  1774         * @private
       
  1775         * @method _moveNode
       
  1776         * @description This method performs the actual element move.
       
  1777         */
       
  1778         _moveNode: function(scroll) {
       
  1779             //if (!this.get(DRAGGING)) {
       
  1780             //    return;
       
  1781             //}
       
  1782             var diffXY = [], diffXY2 = [], startXY = this.nodeXY, xy = this.actXY;
       
  1783 
       
  1784             diffXY[0] = (xy[0] - this.lastXY[0]);
       
  1785             diffXY[1] = (xy[1] - this.lastXY[1]);
       
  1786 
       
  1787             diffXY2[0] = (xy[0] - this.nodeXY[0]);
       
  1788             diffXY2[1] = (xy[1] - this.nodeXY[1]);
       
  1789 
       
  1790 
       
  1791             this.region = {
       
  1792                 '0': xy[0], 
       
  1793                 '1': xy[1],
       
  1794                 area: 0,
       
  1795                 top: xy[1],
       
  1796                 right: xy[0] + this.get(DRAG_NODE).get(OFFSET_WIDTH),
       
  1797                 bottom: xy[1] + this.get(DRAG_NODE).get(OFFSET_HEIGHT),
       
  1798                 left: xy[0]
       
  1799             };
       
  1800 
       
  1801             this.fire(EV_DRAG, {
       
  1802                 pageX: xy[0],
       
  1803                 pageY: xy[1],
       
  1804                 scroll: scroll,
       
  1805                 info: {
       
  1806                     start: startXY,
       
  1807                     xy: xy,
       
  1808                     delta: diffXY,
       
  1809                     offset: diffXY2
       
  1810                 } 
       
  1811             });
       
  1812             
       
  1813             this.lastXY = xy;
       
  1814         },
       
  1815         /**
       
  1816         * @private
       
  1817         * @method _defDragFn
       
  1818         * @description Default function for drag:drag. Fired from _moveNode.
       
  1819         * @param {Event.Facade} ev The drag:drag event
       
  1820         */
       
  1821         _defDragFn: function(e) {
       
  1822             if (this.get('move')) {
       
  1823                 if (e.scroll) {
       
  1824                     e.scroll.node.set('scrollTop', e.scroll.top);
       
  1825                     e.scroll.node.set('scrollLeft', e.scroll.left);
       
  1826                 }
       
  1827                 this.get(DRAG_NODE).setXY([e.pageX, e.pageY]);
       
  1828                 this.realXY = [e.pageX, e.pageY];
       
  1829             }
       
  1830         },
       
  1831         /**
       
  1832         * @private
       
  1833         * @method _move
       
  1834         * @description Fired from DragDropMgr (DDM) on mousemove.
       
  1835         * @param {Event.Facade} ev The mousemove DOM event
       
  1836         */
       
  1837         _move: function(ev) {
       
  1838             if (this.get('lock')) {
       
  1839                 return false;
       
  1840             } else {
       
  1841                 this.mouseXY = [ev.pageX, ev.pageY];
       
  1842                 if (!this._dragThreshMet) {
       
  1843                     var diffX = Math.abs(this.startXY[0] - ev.pageX),
       
  1844                     diffY = Math.abs(this.startXY[1] - ev.pageY);
       
  1845                     if (diffX > this.get('clickPixelThresh') || diffY > this.get('clickPixelThresh')) {
       
  1846                         this._dragThreshMet = true;
       
  1847                         this.start();
       
  1848                         this._alignNode([ev.pageX, ev.pageY]);
       
  1849                     }
       
  1850                 } else {
       
  1851                     if (this._clickTimeout) {
       
  1852                         this._clickTimeout.cancel();
       
  1853                     }
       
  1854                     this._alignNode([ev.pageX, ev.pageY]);
       
  1855                 }
       
  1856             }
       
  1857         },
       
  1858         /**
       
  1859         * @method stopDrag
       
  1860         * @description Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag.
       
  1861         * @return {Self}
       
  1862         * @chainable
       
  1863         */
       
  1864         stopDrag: function() {
       
  1865             if (this.get(DRAGGING)) {
       
  1866                 DDM._end();
       
  1867             }
       
  1868             return this;
       
  1869         },
       
  1870         /**
       
  1871         * @private
       
  1872         * @method destructor
       
  1873         * @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
       
  1874         */
       
  1875         destructor: function() {
       
  1876             this._unprep();
       
  1877             this.detachAll();
       
  1878             if (this.target) {
       
  1879                 this.target.destroy();
       
  1880             }
       
  1881             DDM._unregDrag(this);
       
  1882         }
       
  1883     });
       
  1884     Y.namespace('DD');    
       
  1885     Y.DD.Drag = Drag;
       
  1886 
       
  1887 
       
  1888 
       
  1889 
       
  1890 
       
  1891 }, '3.0.0b1' ,{requires:['dd-ddm-base'], skinnable:false});
       
  1892 YUI.add('dd-proxy', function(Y) {
       
  1893 
       
  1894 
       
  1895     /**
       
  1896      * 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.
       
  1897      * @module dd
       
  1898      * @submodule dd-proxy
       
  1899      */
       
  1900     /**
       
  1901      * This plugin for dd-drag is for creating a proxy drag node, instead of dragging the original node.
       
  1902      * @class DDProxy
       
  1903      * @extends Base
       
  1904      * @constructor
       
  1905      * @namespace Plugin     
       
  1906      */
       
  1907     var DDM = Y.DD.DDM,
       
  1908         NODE = 'node',
       
  1909         DRAG_NODE = 'dragNode',
       
  1910         HOST = 'host',
       
  1911         TRUE = true;
       
  1912 
       
  1913     var P = function(config) {
       
  1914         P.superclass.constructor.apply(this, arguments);
       
  1915     };
       
  1916     
       
  1917     P.NAME = 'DDProxy';
       
  1918     /**
       
  1919     * @property proxy
       
  1920     * @description The Proxy instance will be placed on the Drag instance under the proxy namespace.
       
  1921     * @type {String}
       
  1922     */
       
  1923     P.NS = 'proxy';
       
  1924 
       
  1925     P.ATTRS = {
       
  1926         host: {
       
  1927         },
       
  1928         /**
       
  1929         * @attribute moveOnEnd
       
  1930         * @description Move the original node at the end of the drag. Default: true
       
  1931         * @type Boolean
       
  1932         */
       
  1933         moveOnEnd: {
       
  1934             value: TRUE
       
  1935         },
       
  1936         /**
       
  1937         * @attribute resizeFrame
       
  1938         * @description Make the Proxy node assume the size of the original node. Default: true
       
  1939         * @type Boolean
       
  1940         */
       
  1941         resizeFrame: {
       
  1942             value: TRUE
       
  1943         },
       
  1944         /**
       
  1945         * @attribute positionProxy
       
  1946         * @description Make the Proxy node appear in the same place as the original node. Default: true
       
  1947         * @type Boolean
       
  1948         */
       
  1949         positionProxy: {
       
  1950             value: TRUE
       
  1951         },
       
  1952         /**
       
  1953         * @attribute borderStyle
       
  1954         * @description The default border style for the border of the proxy. Default: 1px solid #808080
       
  1955         * @type Boolean
       
  1956         */
       
  1957         borderStyle: {
       
  1958             value: '1px solid #808080'
       
  1959         }
       
  1960     };
       
  1961 
       
  1962     var proto = {
       
  1963         /**
       
  1964         * @private
       
  1965         * @property _hands
       
  1966         * @description Holds the event handles for setting the proxy
       
  1967         */
       
  1968         _hands: null,
       
  1969         /**
       
  1970         * @private
       
  1971         * @method _init
       
  1972         * @description Handler for the proxy config attribute
       
  1973         */
       
  1974         _init: function() {
       
  1975             if (!DDM._proxy) {
       
  1976                 Y.on('domready', Y.bind(this._init, this));
       
  1977                 return;
       
  1978             }
       
  1979             if (!this._hands) {
       
  1980                 this._hands = [];
       
  1981             }
       
  1982             var i, h, h1, host = this.get(HOST), dnode = host.get(DRAG_NODE);
       
  1983             if (dnode.compareTo(host.get(NODE))) {
       
  1984                 if (DDM._proxy) {
       
  1985                     host.set(DRAG_NODE, DDM._proxy);
       
  1986                 }
       
  1987             }
       
  1988             for (i in this._hands) {
       
  1989                 this._hands[i].detach();
       
  1990             }
       
  1991             h = DDM.on('ddm:start', Y.bind(function() {
       
  1992                 if (DDM.activeDrag === host) {
       
  1993                     DDM._setFrame(host);
       
  1994                 }
       
  1995             }, this));
       
  1996             h1 = DDM.on('ddm:end', Y.bind(function() {
       
  1997                 if (host.get('dragging')) {
       
  1998                     if (this.get('moveOnEnd')) {
       
  1999                         host.get(NODE).setXY(host.lastXY);
       
  2000                     }
       
  2001                     host.get(DRAG_NODE).setStyle('display', 'none');
       
  2002                 }
       
  2003             }, this));
       
  2004             this._hands = [h, h1];
       
  2005         },
       
  2006         initializer: function() {
       
  2007             this._init();
       
  2008         },
       
  2009         destructor: function() {
       
  2010             var host = this.get(HOST);
       
  2011             for (var i in this._hands) {
       
  2012                 this._hands[i].detach();
       
  2013             }
       
  2014             host.set(DRAG_NODE, host.get(NODE));
       
  2015         }
       
  2016     };
       
  2017     
       
  2018     Y.namespace('Plugin');
       
  2019     Y.extend(P, Y.Base, proto);
       
  2020     Y.Plugin.DDProxy = P;
       
  2021 
       
  2022     //Add a couple of methods to the DDM
       
  2023     Y.mix(DDM, {
       
  2024         /**
       
  2025         * @private
       
  2026         * @for DDM
       
  2027         * @namespace DD
       
  2028         * @method _createFrame
       
  2029         * @description Create the proxy element if it doesn't already exist and set the DD.DDM._proxy value
       
  2030         */
       
  2031         _createFrame: function() {
       
  2032             if (!DDM._proxy) {
       
  2033                 DDM._proxy = TRUE;
       
  2034 
       
  2035                 var p = Y.Node.create('<div></div>'),
       
  2036                 b = Y.Node.get('body');
       
  2037 
       
  2038                 p.setStyles({
       
  2039                     position: 'absolute',
       
  2040                     display: 'none',
       
  2041                     zIndex: '999',
       
  2042                     top: '-999px',
       
  2043                     left: '-999px'
       
  2044                 });
       
  2045 
       
  2046                 b.insertBefore(p, b.get('firstChild'));
       
  2047                 p.set('id', Y.stamp(p));
       
  2048                 p.addClass(DDM.CSS_PREFIX + '-proxy');
       
  2049                 DDM._proxy = p;
       
  2050             }
       
  2051         },
       
  2052         /**
       
  2053         * @private
       
  2054         * @for DDM
       
  2055         * @namespace DD
       
  2056         * @method _setFrame
       
  2057         * @description If resizeProxy is set to true (default) it will resize the proxy element to match the size of the Drag Element.
       
  2058         * If positionProxy is set to true (default) it will position the proxy element in the same location as the Drag Element.
       
  2059         */
       
  2060         _setFrame: function(drag) {
       
  2061             var n = drag.get(NODE), d = drag.get(DRAG_NODE), ah, cur = 'auto';
       
  2062             if (drag.proxy.get('resizeFrame')) {
       
  2063                 DDM._proxy.setStyles({
       
  2064                     height: n.get('offsetHeight') + 'px',
       
  2065                     width: n.get('offsetWidth') + 'px'
       
  2066                 });
       
  2067             }
       
  2068             
       
  2069             ah = DDM.activeDrag.get('activeHandle');
       
  2070             if (ah) {
       
  2071                 cur = ah.getStyle('cursor');
       
  2072             }
       
  2073             if (cur == 'auto') {
       
  2074                 cur = DDM.get('dragCursor');
       
  2075             }
       
  2076 
       
  2077 
       
  2078             d.setStyles({
       
  2079                 visibility: 'hidden',
       
  2080                 display: 'block',
       
  2081                 cursor: cur,
       
  2082                 border: drag.proxy.get('borderStyle')
       
  2083             });
       
  2084 
       
  2085 
       
  2086 
       
  2087             if (drag.proxy.get('positionProxy')) {
       
  2088                 d.setXY(drag.nodeXY);
       
  2089             }
       
  2090             d.setStyle('visibility', 'visible');
       
  2091         }
       
  2092     });
       
  2093 
       
  2094     //Create the frame when DOM is ready
       
  2095     Y.on('domready', Y.bind(DDM._createFrame, DDM));
       
  2096 
       
  2097 
       
  2098 
       
  2099 }, '3.0.0b1' ,{requires:['dd-ddm', 'dd-drag'], skinnable:false});
       
  2100 YUI.add('dd-constrain', function(Y) {
       
  2101 
       
  2102 
       
  2103     /**
       
  2104      * 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.
       
  2105      * @module dd
       
  2106      * @submodule dd-constrain
       
  2107      */
       
  2108     /**
       
  2109      * This is a plugin for the dd-drag module to add the constraining methods to it. It supports constraining to a renodenode or viewport. It anode* supports tick based moves and XY axis constraints.
       
  2110      * @class DragConstrained
       
  2111      * @extends Base
       
  2112      * @constructor
       
  2113      * @namespace Plugin     
       
  2114      */
       
  2115 
       
  2116     var DRAG_NODE = 'dragNode',
       
  2117         OFFSET_HEIGHT = 'offsetHeight',
       
  2118         OFFSET_WIDTH = 'offsetWidth',
       
  2119         HOST = 'host',
       
  2120         CON_2_REGION = 'constrain2region',
       
  2121         CON_2_NODE = 'constrain2node',
       
  2122         TICK_X_ARRAY = 'tickXArray',
       
  2123         TICK_Y_ARRAY = 'tickYArray',
       
  2124         DDM = Y.DD.DDM,
       
  2125         TOP = 'top',
       
  2126         RIGHT = 'right',
       
  2127         BOTTOM = 'bottom',
       
  2128         LEFT = 'left',
       
  2129         proto = null;
       
  2130 
       
  2131     var C = function(config) {
       
  2132         C.superclass.constructor.apply(this, arguments);
       
  2133     };
       
  2134     
       
  2135     C.NAME = 'DragConstrained';
       
  2136     /**
       
  2137     * @property con
       
  2138     * @description The Constrained instance will be placed on the Drag instance under the con namespace.
       
  2139     * @type {String}
       
  2140     */
       
  2141     C.NS = 'con';
       
  2142 
       
  2143     C.ATTRS = {
       
  2144         host: {
       
  2145         },
       
  2146         /**
       
  2147         * @attribute stickX
       
  2148         * @description Stick the drag movement to the X-Axis. Default: false
       
  2149         * @type Boolean
       
  2150         */        
       
  2151         stickX: {
       
  2152             value: false
       
  2153         },
       
  2154         /**
       
  2155         * @attribute stickY
       
  2156         * @description Stick the drag movement to the Y-Axis
       
  2157         * @type Boolean
       
  2158         */        
       
  2159         stickY: {
       
  2160             value: false
       
  2161         },
       
  2162         /**
       
  2163         * @attribute tickX
       
  2164         * @description The X tick offset the drag node should snap to on each drag move. False for no ticks. Default: false
       
  2165         * @type Number/false
       
  2166         */        
       
  2167         tickX: {
       
  2168             value: false
       
  2169         },
       
  2170         /**
       
  2171         * @attribute tickY
       
  2172         * @description The Y tick offset the drag node should snap to on each drag move. False for no ticks. Default: false
       
  2173         * @type Number/false
       
  2174         */        
       
  2175         tickY: {
       
  2176             value: false
       
  2177         },
       
  2178         /**
       
  2179         * @attribute tickXArray
       
  2180         * @description An array of page coordinates to use as X ticks for drag movement.
       
  2181         * @type Array
       
  2182         */
       
  2183         tickXArray: {
       
  2184             value: false
       
  2185         },
       
  2186         /**
       
  2187         * @attribute tickYArray
       
  2188         * @description An array of page coordinates to use as Y ticks for drag movement.
       
  2189         * @type Array
       
  2190         */
       
  2191         tickYArray: {
       
  2192             value: false
       
  2193         },
       
  2194         /**
       
  2195         * @attribute constrain2region
       
  2196         * @description An Object Literal containing a valid region (top, right, bottom, left) of page positions to constrain the drag node to.
       
  2197         * @type Object
       
  2198         */
       
  2199         constrain2region: {
       
  2200             value: false,
       
  2201             getter: function(r) {
       
  2202                 if (Y.Lang.isObject(r)) {
       
  2203                     var o = {};
       
  2204                     Y.mix(o, r);
       
  2205                     return o;
       
  2206                 } else {
       
  2207                     return false;
       
  2208                 }
       
  2209             },
       
  2210             setter: function (r) {
       
  2211                 if (Y.Lang.isObject(r)) {
       
  2212                     if (Y.Lang.isNumber(r[TOP]) && Y.Lang.isNumber(r[RIGHT]) && Y.Lang.isNumber(r[LEFT]) && Y.Lang.isNumber(r[BOTTOM])) {
       
  2213                         var o = {};
       
  2214                         Y.mix(o, r);
       
  2215                         return o;
       
  2216                     } else {
       
  2217                         return false;
       
  2218                     }
       
  2219                 } else if (r !== false) {
       
  2220                     return false;
       
  2221                 }
       
  2222                 return r;
       
  2223             }
       
  2224         },
       
  2225         /**
       
  2226         * @attribute gutter
       
  2227         * @description CSS style string for the gutter of a region (supports negative values): '5 0' (sets top and bottom to 5px, left and right to 0px), '1 2 3 4' (top 1px, right 2px, bottom 3px, left 4px)        
       
  2228         * @type String
       
  2229         */
       
  2230         gutter: {
       
  2231             value: '0',
       
  2232             setter: function(gutter) {
       
  2233                 return Y.DD.DDM.cssSizestoObject(gutter);
       
  2234             }
       
  2235         },
       
  2236         /**
       
  2237         * @attribute constrain2node
       
  2238         * @description Will attempt to constrain the drag node to the bounderies of this node.
       
  2239         * @type Object
       
  2240         */
       
  2241         constrain2node: {
       
  2242             value: false,
       
  2243             setter: function(n) {
       
  2244                 if (!this.get(CON_2_REGION)) {
       
  2245                     var node = Y.Node.get(n);
       
  2246                     if (node) {
       
  2247                         return node;
       
  2248                     }
       
  2249                 } else if (this.get(CON_2_REGION) !== false) {
       
  2250                 }
       
  2251                 return false;
       
  2252             }
       
  2253         },
       
  2254         /**
       
  2255         * @attribute constrain2view
       
  2256         * @description Will attempt to constrain the drag node to the bounderies of the viewport region.
       
  2257         * @type Object
       
  2258         */
       
  2259         constrain2view: {
       
  2260             value: false
       
  2261         }
       
  2262     };
       
  2263 
       
  2264     proto = {
       
  2265         initializer: function() {
       
  2266             this.get(HOST).on('drag:start', Y.bind(this._handleStart, this));
       
  2267             this.get(HOST).after('drag:align', Y.bind(this.align, this));
       
  2268         },
       
  2269         /**
       
  2270         * @private
       
  2271         * @method _handleStart
       
  2272         * @description Fires on drag:start and clears the _regionCache
       
  2273         */
       
  2274         _handleStart: function() {
       
  2275             this._regionCache = null;
       
  2276         },
       
  2277         /**
       
  2278         * @private
       
  2279         * @property _regionCache
       
  2280         * @description Store a cache of the region that we are constraining to
       
  2281         * @type Object
       
  2282         */
       
  2283         _regionCache: null,
       
  2284         /**
       
  2285         * @private
       
  2286         * @method _cacheRegion
       
  2287         * @description Get's the region and caches it, called from window.resize and when the cache is null
       
  2288         */
       
  2289         _cacheRegion: function() {
       
  2290             this._regionCache = this.get(CON_2_NODE).get('region');
       
  2291         },
       
  2292         /**
       
  2293         * @method getRegion
       
  2294         * @description Get the active region: viewport, node, custom region
       
  2295         * @param {Boolean} inc Include the node's height and width
       
  2296         * @return {Object}
       
  2297         */
       
  2298         getRegion: function(inc) {
       
  2299             var r = {}, oh = null, ow = null,
       
  2300                 g = this.get('gutter'),
       
  2301                 host = this.get(HOST);
       
  2302 
       
  2303             if (this.get(CON_2_NODE)) {
       
  2304                 if (!this._regionCache) {
       
  2305                     Y.on('resize', Y.bind(this._cacheRegion, this), window);
       
  2306                     this._cacheRegion();
       
  2307                 }
       
  2308                 r = Y.clone(this._regionCache);
       
  2309             } else if (this.get(CON_2_REGION)) {
       
  2310                 r = this.get(CON_2_REGION);
       
  2311             } else if (this.get('constrain2view')) {
       
  2312                 r = host.get(DRAG_NODE).get('viewportRegion');
       
  2313             } else {
       
  2314                 return false;
       
  2315             }
       
  2316 
       
  2317             Y.each(g, function(i, n) {
       
  2318                 if ((n == RIGHT) || (n == BOTTOM)) {
       
  2319                     r[n] -= i;
       
  2320                 } else {
       
  2321                     r[n] += i;
       
  2322                 }
       
  2323             });
       
  2324             if (inc) {
       
  2325                 oh = host.get(DRAG_NODE).get(OFFSET_HEIGHT);
       
  2326                 ow = host.get(DRAG_NODE).get(OFFSET_WIDTH);
       
  2327                 r[RIGHT] = r[RIGHT] - ow;
       
  2328                 r[BOTTOM] = r[BOTTOM] - oh;
       
  2329             }
       
  2330             return r;
       
  2331         },
       
  2332         /**
       
  2333         * @private
       
  2334         * @method _checkRegion
       
  2335         * @description Check if xy is inside a given region, if not change to it be inside.
       
  2336         * @param {Array} _xy The XY to check if it's in the current region, if it isn't inside the region, it will reset the xy array to be inside the region.
       
  2337         * @return {Array} The new XY that is inside the region
       
  2338         */
       
  2339         _checkRegion: function(_xy) {
       
  2340             var oxy = _xy,
       
  2341                 r = this.getRegion(),
       
  2342                 host = this.get(HOST),
       
  2343                 oh = host.get(DRAG_NODE).get(OFFSET_HEIGHT),
       
  2344                 ow = host.get(DRAG_NODE).get(OFFSET_WIDTH);
       
  2345             
       
  2346                 if (oxy[1] > (r[BOTTOM] - oh)) {
       
  2347                     _xy[1] = (r[BOTTOM] - oh);
       
  2348                 }
       
  2349                 if (r[TOP] > oxy[1]) {
       
  2350                     _xy[1] = r[TOP];
       
  2351 
       
  2352                 }
       
  2353                 if (oxy[0] > (r[RIGHT] - ow)) {
       
  2354                     _xy[0] = (r[RIGHT] - ow);
       
  2355                 }
       
  2356                 if (r[LEFT] > oxy[0]) {
       
  2357                     _xy[0] = r[LEFT];
       
  2358                 }
       
  2359 
       
  2360             return _xy;
       
  2361         },
       
  2362         /**
       
  2363         * @method inRegion
       
  2364         * @description Checks if the XY passed or the dragNode is inside the active region.
       
  2365         * @param {Array} xy Optional XY to check, if not supplied this.get('dragNode').getXY() is used.
       
  2366         * @return {Boolean} True if the XY is inside the region, false otherwise.
       
  2367         */
       
  2368         inRegion: function(xy) {
       
  2369             xy = xy || this.get(HOST).get(DRAG_NODE).getXY();
       
  2370 
       
  2371             var _xy = this._checkRegion([xy[0], xy[1]]),
       
  2372                 inside = false;
       
  2373                 if ((xy[0] === _xy[0]) && (xy[1] === _xy[1])) {
       
  2374                     inside = true;
       
  2375                 }
       
  2376             return inside;
       
  2377         },
       
  2378         /**
       
  2379         * @method align
       
  2380         * @description Modifies the Drag.actXY method from the after drag:align event. This is where the constraining happens.
       
  2381         */
       
  2382         align: function() {
       
  2383             var host = this.get(HOST),
       
  2384                 _xy = host.actXY,
       
  2385                 r = this.getRegion(true);
       
  2386 
       
  2387             if (this.get('stickX')) {
       
  2388                 _xy[1] = (host.startXY[1] - host.deltaXY[1]);
       
  2389             }
       
  2390             if (this.get('stickY')) {
       
  2391                 _xy[0] = (host.startXY[0] - host.deltaXY[0]);
       
  2392             }
       
  2393 
       
  2394             if (r) {
       
  2395                 _xy = this._checkRegion(_xy);
       
  2396             }
       
  2397                 
       
  2398             _xy = this._checkTicks(_xy, r);
       
  2399             host.actXY = _xy;
       
  2400         },
       
  2401         /**
       
  2402         * @private
       
  2403         * @method _checkTicks
       
  2404         * @description This method delegates the proper helper method for tick calculations
       
  2405         * @param {Array} xy The XY coords for the Drag
       
  2406         * @param {Object} r The optional region that we are bound to.
       
  2407         * @return {Array} The calced XY coords
       
  2408         */
       
  2409         _checkTicks: function(xy, r) {
       
  2410             var host = this.get(HOST),
       
  2411                 lx = (host.startXY[0] - host.deltaXY[0]),
       
  2412                 ly = (host.startXY[1] - host.deltaXY[1]),
       
  2413                 xt = this.get('tickX'),
       
  2414                 yt = this.get('tickY');
       
  2415                 if (xt && !this.get(TICK_X_ARRAY)) {
       
  2416                     xy[0] = DDM._calcTicks(xy[0], lx, xt, r[LEFT], r[RIGHT]);
       
  2417                 }
       
  2418                 if (yt && !this.get(TICK_Y_ARRAY)) {
       
  2419                     xy[1] = DDM._calcTicks(xy[1], ly, yt, r[TOP], r[BOTTOM]);
       
  2420                 }
       
  2421                 if (this.get(TICK_X_ARRAY)) {
       
  2422                     xy[0] = DDM._calcTickArray(xy[0], this.get(TICK_X_ARRAY), r[LEFT], r[RIGHT]);
       
  2423                 }
       
  2424                 if (this.get(TICK_Y_ARRAY)) {
       
  2425                     xy[1] = DDM._calcTickArray(xy[1], this.get(TICK_Y_ARRAY), r[TOP], r[BOTTOM]);
       
  2426                 }
       
  2427 
       
  2428             return xy;
       
  2429         }
       
  2430     };
       
  2431 
       
  2432     Y.namespace('Plugin');
       
  2433     Y.extend(C, Y.Base, proto);
       
  2434     Y.Plugin.DDConstrained = C;
       
  2435 
       
  2436     Y.mix(DDM, {
       
  2437         /**
       
  2438         * @for DDM
       
  2439         * @namespace DD
       
  2440         * @private
       
  2441         * @method _calcTicks
       
  2442         * @description Helper method to calculate the tick offsets for a given position
       
  2443         * @param {Number} pos The current X or Y position
       
  2444         * @param {Number} start The start X or Y position
       
  2445         * @param {Number} tick The X or Y tick increment
       
  2446         * @param {Number} off1 The min offset that we can't pass (region)
       
  2447         * @param {Number} off2 The max offset that we can't pass (region)
       
  2448         * @return {Number} The new position based on the tick calculation
       
  2449         */
       
  2450         _calcTicks: function(pos, start, tick, off1, off2) {
       
  2451             var ix = ((pos - start) / tick),
       
  2452                 min = Math.floor(ix),
       
  2453                 max = Math.ceil(ix);
       
  2454                 if ((min !== 0) || (max !== 0)) {
       
  2455                     if ((ix >= min) && (ix <= max)) {
       
  2456                         pos = (start + (tick * min));
       
  2457                         if (off1 && off2) {
       
  2458                             if (pos < off1) {
       
  2459                                 pos = (start + (tick * (min + 1)));
       
  2460                             }
       
  2461                             if (pos > off2) {
       
  2462                                 pos = (start + (tick * (min - 1)));
       
  2463                             }
       
  2464                         }
       
  2465                     }
       
  2466                 }
       
  2467                 return pos;
       
  2468         },
       
  2469         /**
       
  2470         * @for DDM
       
  2471         * @namespace DD
       
  2472         * @private
       
  2473         * @method _calcTickArray
       
  2474         * @description This method is used with the tickXArray and tickYArray config options
       
  2475         * @param {Number} pos The current X or Y position
       
  2476         * @param {Number} ticks The array containing our custom tick positions.
       
  2477         * @param {Number} off1 The min offset that we can't pass (region)
       
  2478         * @param {Number} off2 The max offset that we can't pass (region)
       
  2479         * @return The tick position
       
  2480         */
       
  2481         _calcTickArray: function(pos, ticks, off1, off2) {
       
  2482             var i = 0, len = ticks.length, next = 0,
       
  2483                 diff1, diff2, ret;
       
  2484 
       
  2485             if (!ticks || (ticks.length === 0)) {
       
  2486                 return pos;
       
  2487             } else if (ticks[0] >= pos) {
       
  2488                 return ticks[0];
       
  2489             } else {
       
  2490                 for (i = 0; i < len; i++) {
       
  2491                     next = (i + 1);
       
  2492                     if (ticks[next] && ticks[next] >= pos) {
       
  2493                         diff1 = pos - ticks[i];
       
  2494                         diff2 = ticks[next] - pos;
       
  2495                         ret = (diff2 > diff1) ? ticks[i] : ticks[next];
       
  2496                         if (off1 && off2) {
       
  2497                             if (ret > off2) {
       
  2498                                 if (ticks[i]) {
       
  2499                                     ret = ticks[i];
       
  2500                                 } else {
       
  2501                                     ret = ticks[len - 1];
       
  2502                                 }
       
  2503                             }
       
  2504                         }
       
  2505                         return ret;
       
  2506                     }
       
  2507                     
       
  2508                 }
       
  2509                 return ticks[ticks.length - 1];
       
  2510             }
       
  2511         }
       
  2512     });
       
  2513 
       
  2514 
       
  2515 
       
  2516 
       
  2517 }, '3.0.0b1' ,{requires:['dd-drag'], skinnable:false});
       
  2518 YUI.add('dd-scroll', function(Y) {
       
  2519 
       
  2520 
       
  2521     /**
       
  2522      * 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.
       
  2523      * @module dd
       
  2524      * @submodule dd-scroll
       
  2525      */
       
  2526     /**
       
  2527      * This class is the base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
       
  2528      * This class should not be called on it's own, it's designed to be a plugin.
       
  2529      * @class Scroll
       
  2530      * @extends Base
       
  2531      * @namespace DD
       
  2532      * @constructor
       
  2533      */
       
  2534 
       
  2535     var S = function() {
       
  2536         S.superclass.constructor.apply(this, arguments);
       
  2537 
       
  2538     },
       
  2539     HOST = 'host',
       
  2540     BUFFER = 'buffer',
       
  2541     PARENT_SCROLL = 'parentScroll',
       
  2542     WINDOW_SCROLL = 'windowScroll',
       
  2543     SCROLL_TOP = 'scrollTop',
       
  2544     SCROLL_LEFT = 'scrollLeft',
       
  2545     OFFSET_WIDTH = 'offsetWidth',
       
  2546     OFFSET_HEIGHT = 'offsetHeight';
       
  2547 
       
  2548 
       
  2549     S.ATTRS = {
       
  2550         /**
       
  2551         * @attribute parentScroll
       
  2552         * @description Internal config option to hold the node that we are scrolling. Should not be set by the developer.
       
  2553         * @type Node
       
  2554         */
       
  2555         parentScroll: {
       
  2556             value: false,
       
  2557             setter: function(node) {
       
  2558                 if (node) {
       
  2559                     return node;
       
  2560                 }
       
  2561                 return false;
       
  2562             }
       
  2563         },
       
  2564         /**
       
  2565         * @attribute buffer
       
  2566         * @description The number of pixels from the edge of the screen to turn on scrolling. Default: 30
       
  2567         * @type Number
       
  2568         */
       
  2569         buffer: {
       
  2570             value: 30
       
  2571         },
       
  2572         /**
       
  2573         * @attribute scrollDelay
       
  2574         * @description The number of milliseconds delay to pass to the auto scroller. Default: 235
       
  2575         * @type Number
       
  2576         */
       
  2577         scrollDelay: {
       
  2578             value: 235
       
  2579         },
       
  2580         /**
       
  2581         * @attribute host
       
  2582         * @description The host we are plugged into.
       
  2583         * @type Object
       
  2584         */
       
  2585         host: {
       
  2586             value: null
       
  2587         },
       
  2588         /**
       
  2589         * @attribute windowScroll
       
  2590         * @description Turn on window scroll support, default: false
       
  2591         * @type Boolean
       
  2592         */
       
  2593         windowScroll: {
       
  2594             value: false
       
  2595         },
       
  2596         /**
       
  2597         * @attribute vertical
       
  2598         * @description Allow vertical scrolling, default: true.
       
  2599         * @type Boolean
       
  2600         */
       
  2601         vertical: {
       
  2602             value: true
       
  2603         },
       
  2604         /**
       
  2605         * @attribute horizontal
       
  2606         * @description Allow horizontal scrolling, default: true.
       
  2607         * @type Boolean
       
  2608         */
       
  2609         horizontal: {
       
  2610             value: true
       
  2611         }
       
  2612     };
       
  2613 
       
  2614     Y.extend(S, Y.Base, {
       
  2615         /**
       
  2616         * @private
       
  2617         * @property _scrolling
       
  2618         * @description Tells if we are actively scrolling or not.
       
  2619         * @type Boolean
       
  2620         */
       
  2621         _scrolling: null,
       
  2622         /**
       
  2623         * @private
       
  2624         * @property _vpRegionCache
       
  2625         * @description Cache of the Viewport dims.
       
  2626         * @type Object
       
  2627         */
       
  2628         _vpRegionCache: null,
       
  2629         /**
       
  2630         * @private
       
  2631         * @property _dimCache
       
  2632         * @description Cache of the dragNode dims.
       
  2633         * @type Object
       
  2634         */
       
  2635         _dimCache: null,
       
  2636         /**
       
  2637         * @private
       
  2638         * @property _scrollTimer
       
  2639         * @description Holder for the Timer object returned from Y.later.
       
  2640         * @type {Y.later}
       
  2641         */
       
  2642         _scrollTimer: null,
       
  2643         /**
       
  2644         * @private
       
  2645         * @method _getVPRegion
       
  2646         * @description Sets the _vpRegionCache property with an Object containing the dims from the viewport.
       
  2647         */        
       
  2648         _getVPRegion: function() {
       
  2649             var r = {};
       
  2650             //if (!this._vpRegionCache) {
       
  2651                 var n = this.get(PARENT_SCROLL),
       
  2652                 b = this.get(BUFFER),
       
  2653                 ws = this.get(WINDOW_SCROLL),
       
  2654                 xy = ((ws) ? [] : n.getXY()),
       
  2655                 w = ((ws) ? 'winWidth' : OFFSET_WIDTH),
       
  2656                 h = ((ws) ? 'winHeight' : OFFSET_HEIGHT),
       
  2657                 t = ((ws) ? n.get(SCROLL_TOP) : xy[1]),
       
  2658                 l = ((ws) ? n.get(SCROLL_LEFT) : xy[0]);
       
  2659 
       
  2660                 r = {
       
  2661                     top: t + b,
       
  2662                     right: (n.get(w) + l) - b,
       
  2663                     bottom: (n.get(h) + t) - b,
       
  2664                     left: l + b
       
  2665                 };
       
  2666                 this._vpRegionCache = r;
       
  2667             //} else {
       
  2668             //    r = this._vpRegionCache;
       
  2669             //}
       
  2670             return r;
       
  2671         },
       
  2672         initializer: function() {
       
  2673             var h = this.get(HOST);
       
  2674             h.after('drag:start', Y.bind(this.start, this));
       
  2675             h.after('drag:end', Y.bind(this.end, this));
       
  2676             h.on('drag:align', Y.bind(this.align, this));
       
  2677 
       
  2678             //TODO - This doesn't work yet??
       
  2679             Y.get(window).on('scroll', Y.bind(function() {
       
  2680                 this._vpRegionCache = null;
       
  2681             }, this));
       
  2682         },
       
  2683         /**
       
  2684         * @private
       
  2685         * @method _checkWinScroll
       
  2686         * @description Check to see if we need to fire the scroll timer. If scroll timer is running this will scroll the window.
       
  2687         * @param {Boolean} move Should we move the window. From Y.later
       
  2688         */        
       
  2689         _checkWinScroll: function(move) {
       
  2690             var r = this._getVPRegion(),
       
  2691                 ho = this.get(HOST),
       
  2692                 ws = this.get(WINDOW_SCROLL),
       
  2693                 xy = ho.lastXY,
       
  2694                 scroll = false,
       
  2695                 b = this.get(BUFFER),
       
  2696                 win = this.get(PARENT_SCROLL),
       
  2697                 sTop = win.get(SCROLL_TOP),
       
  2698                 sLeft = win.get(SCROLL_LEFT),
       
  2699                 w = this._dimCache.w,
       
  2700                 h = this._dimCache.h,
       
  2701                 bottom = xy[1] + h,
       
  2702                 top = xy[1],
       
  2703                 right = xy[0] + w,
       
  2704                 left = xy[0],
       
  2705                 nt = top,
       
  2706                 nl = left,
       
  2707                 st = sTop,
       
  2708                 sl = sLeft;
       
  2709             
       
  2710             if (this.get('horizontal')) {
       
  2711                 if (left <= r.left) {
       
  2712                     scroll = true;
       
  2713                     nl = xy[0] - ((ws) ? b : 0);
       
  2714                     sl = sLeft - b;
       
  2715                 }
       
  2716                 if (right >= r.right) {
       
  2717                     scroll = true;
       
  2718                     nl = xy[0] + ((ws) ? b : 0);
       
  2719                     sl = sLeft + b;
       
  2720                 }
       
  2721             }
       
  2722             if (this.get('vertical')) {
       
  2723                 if (bottom >= r.bottom) {
       
  2724                     scroll = true;
       
  2725                     nt = xy[1] + ((ws) ? b : 0);
       
  2726                     st = sTop + b;
       
  2727 
       
  2728                 }
       
  2729                 if (top <= r.top) {
       
  2730                     scroll = true;
       
  2731                     nt = xy[1] - ((ws) ? b : 0);
       
  2732                     st = sTop - b;
       
  2733                 }
       
  2734             }
       
  2735 
       
  2736             if (st < 0) {
       
  2737                 st = 0;
       
  2738                 nt = xy[1];
       
  2739             }
       
  2740 
       
  2741             if (sl < 0) {
       
  2742                 sl = 0;
       
  2743                 nl = xy[0];
       
  2744             }
       
  2745 
       
  2746             if (nt < 0) {
       
  2747                 nt = xy[1];
       
  2748             }
       
  2749             if (nl < 0) {
       
  2750                 nl = xy[0];
       
  2751             }
       
  2752             if (move) {
       
  2753                 ho.actXY = [nl, nt];
       
  2754                 ho._moveNode({ node: win, top: st, left: sl});
       
  2755                 if (!st && !sl) {
       
  2756                     this._cancelScroll();
       
  2757                 }
       
  2758             } else {
       
  2759                 if (scroll) {
       
  2760                     this._initScroll();
       
  2761                 } else {
       
  2762                     this._cancelScroll();
       
  2763                 }
       
  2764             }
       
  2765         },
       
  2766         /**
       
  2767         * @private
       
  2768         * @method _initScroll
       
  2769         * @description Cancel a previous scroll timer and init a new one.
       
  2770         */        
       
  2771         _initScroll: function() {
       
  2772             this._cancelScroll();
       
  2773             this._scrollTimer = Y.Lang.later(this.get('scrollDelay'), this, this._checkWinScroll, [true], true);
       
  2774 
       
  2775         },
       
  2776         /**
       
  2777         * @private
       
  2778         * @method _cancelScroll
       
  2779         * @description Cancel a currently running scroll timer.
       
  2780         */        
       
  2781         _cancelScroll: function() {
       
  2782             this._scrolling = false;
       
  2783             if (this._scrollTimer) {
       
  2784                 this._scrollTimer.cancel();
       
  2785                 delete this._scrollTimer;
       
  2786             }
       
  2787         },
       
  2788         /**
       
  2789         * @method align
       
  2790         * @description Called from the drag:align event to determine if we need to scroll.
       
  2791         */        
       
  2792         align: function(e) {
       
  2793             if (this._scrolling) {
       
  2794                 this._cancelScroll();
       
  2795                 e.preventDefault();
       
  2796             }
       
  2797             if (!this._scrolling) {
       
  2798                 this._checkWinScroll();
       
  2799             }
       
  2800         },
       
  2801         /**
       
  2802         * @private
       
  2803         * @method _setDimCache
       
  2804         * @description Set the cache of the dragNode dims.
       
  2805         */        
       
  2806         _setDimCache: function() {
       
  2807             var node = this.get(HOST).get('dragNode');
       
  2808             this._dimCache = {
       
  2809                 h: node.get(OFFSET_HEIGHT),
       
  2810                 w: node.get(OFFSET_WIDTH)
       
  2811             };
       
  2812         },
       
  2813         /**
       
  2814         * @method start
       
  2815         * @description Called from the drag:start event
       
  2816         */
       
  2817         start: function() {
       
  2818             this._setDimCache();
       
  2819         },
       
  2820         /**
       
  2821         * @method end
       
  2822         * @description Called from the drag:end event
       
  2823         */
       
  2824         end: function(xy) {
       
  2825             this._dimCache = null;
       
  2826             this._cancelScroll();
       
  2827         },
       
  2828         /**
       
  2829         * @method toString
       
  2830         * @description General toString method for logging
       
  2831         * @return String name for the object
       
  2832         */
       
  2833         toString: function() {
       
  2834             return S.NAME + ' #' + this.get('node').get('id');
       
  2835         }
       
  2836     });
       
  2837 
       
  2838     Y.namespace('Plugin');
       
  2839 
       
  2840     
       
  2841     /**
       
  2842      * Extends the Scroll class to make the window scroll while dragging.
       
  2843      * @class DDWindowScroll
       
  2844      * @extends DD.Scroll
       
  2845      * @namespace Plugin
       
  2846      * @constructor
       
  2847      */
       
  2848     var WS = function() {
       
  2849         WS.superclass.constructor.apply(this, arguments);
       
  2850     };
       
  2851     WS.ATTRS = Y.merge(S.ATTRS, {
       
  2852         /**
       
  2853         * @attribute windowScroll
       
  2854         * @description Turn on window scroll support, default: true
       
  2855         * @type Boolean
       
  2856         */
       
  2857         windowScroll: {
       
  2858             value: true,
       
  2859             setter: function(scroll) {
       
  2860                 if (scroll) {
       
  2861                     this.set(PARENT_SCROLL, Y.get(window));
       
  2862                 }
       
  2863                 return scroll;
       
  2864             }
       
  2865         }
       
  2866     });
       
  2867     Y.extend(WS, S, {
       
  2868         //Shouldn't have to do this..
       
  2869         initializer: function() {
       
  2870             this.set('windowScroll', this.get('windowScroll'));
       
  2871         }
       
  2872     });
       
  2873     WS.NAME = WS.NS = 'winscroll';
       
  2874     Y.Plugin.DDWinScroll = WS;
       
  2875     
       
  2876 
       
  2877     /**
       
  2878      * Extends the Scroll class to make a parent node scroll while dragging.
       
  2879      * @class DDNodeScroll
       
  2880      * @extends DD.Scroll
       
  2881      * @namespace Plugin
       
  2882      * @constructor
       
  2883      */
       
  2884     var NS = function() {
       
  2885         NS.superclass.constructor.apply(this, arguments);
       
  2886 
       
  2887     };
       
  2888     NS.ATTRS = Y.merge(S.ATTRS, {
       
  2889         /**
       
  2890         * @attribute node
       
  2891         * @description The node we want to scroll. Used to set the internal parentScroll attribute.
       
  2892         * @type Node
       
  2893         */
       
  2894         node: {
       
  2895             value: false,
       
  2896             setter: function(node) {
       
  2897                 var n = Y.get(node);
       
  2898                 if (!n) {
       
  2899                     if (node !== false) {
       
  2900                         Y.error('DDNodeScroll: Invalid Node Given: ' + node);
       
  2901                     }
       
  2902                 } else {
       
  2903                     n = n.item(0);
       
  2904                     this.set(PARENT_SCROLL, n);
       
  2905                 }
       
  2906                 return n;
       
  2907             }
       
  2908         }
       
  2909     });
       
  2910     Y.extend(NS, S, {
       
  2911         //Shouldn't have to do this..
       
  2912         initializer: function() {
       
  2913             this.set('node', this.get('node'));
       
  2914         }
       
  2915     });
       
  2916     NS.NAME = NS.NS = 'nodescroll';
       
  2917     Y.Plugin.DDNodeScroll = NS;
       
  2918 
       
  2919     Y.DD.Scroll = S;    
       
  2920 
       
  2921 
       
  2922 
       
  2923 }, '3.0.0b1' ,{skinnable:false, requires:['dd-drag'], optional:['dd-proxy']});
       
  2924 YUI.add('dd-plugin', function(Y) {
       
  2925 
       
  2926 
       
  2927        /**
       
  2928         * This is a simple Drag plugin that can be attached to a Node via the plug method.
       
  2929         * @module dd
       
  2930         * @submodule dd-plugin
       
  2931         */
       
  2932        /**
       
  2933         * This is a simple Drag plugin that can be attached to a Node via the plug method.
       
  2934         * @class Drag
       
  2935         * @extends DD.Drag
       
  2936         * @constructor
       
  2937         * @namespace Plugin
       
  2938         */
       
  2939 
       
  2940 
       
  2941         var Drag = function(config) {
       
  2942             config.node = config.host;
       
  2943             Drag.superclass.constructor.apply(this, arguments);
       
  2944         };
       
  2945         
       
  2946         /**
       
  2947         * @property NAME
       
  2948         * @description dd-plugin
       
  2949         * @type {String}
       
  2950         */
       
  2951         Drag.NAME = "dd-plugin";
       
  2952 
       
  2953         /**
       
  2954         * @property NS
       
  2955         * @description The Drag instance will be placed on the Node instance under the dd namespace. It can be accessed via Node.dd;
       
  2956         * @type {String}
       
  2957         */
       
  2958         Drag.NS = "dd";
       
  2959 
       
  2960 
       
  2961         Y.extend(Drag, Y.DD.Drag);
       
  2962         Y.namespace('Plugin');
       
  2963         Y.Plugin.Drag = Drag;
       
  2964 
       
  2965 
       
  2966 
       
  2967 
       
  2968 
       
  2969 }, '3.0.0b1' ,{skinnable:false, requires:['dd-drag'], optional:['dd-constrain', 'dd-proxy']});
       
  2970 YUI.add('dd-drop', function(Y) {
       
  2971 
       
  2972 
       
  2973     /**
       
  2974      * 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.
       
  2975      * @module dd
       
  2976      * @submodule dd-drop
       
  2977      */     
       
  2978     /**
       
  2979      * This class provides the ability to create a Drop Target.
       
  2980      * @class Drop
       
  2981      * @extends Base
       
  2982      * @constructor
       
  2983      * @namespace DD
       
  2984      */
       
  2985 
       
  2986     var NODE = 'node',
       
  2987         DDM = Y.DD.DDM,
       
  2988         OFFSET_HEIGHT = 'offsetHeight',
       
  2989         OFFSET_WIDTH = 'offsetWidth',
       
  2990         /**
       
  2991         * @event drop:over
       
  2992         * @description Fires when a drag element is over this target.
       
  2993         * @bubbles DDM
       
  2994         * @type {Event.Custom}
       
  2995         */
       
  2996         EV_DROP_OVER = 'drop:over',
       
  2997         /**
       
  2998         * @event drop:enter
       
  2999         * @description Fires when a drag element enters this target.
       
  3000         * @bubbles DDM
       
  3001         * @type {Event.Custom}
       
  3002         */
       
  3003         EV_DROP_ENTER = 'drop:enter',
       
  3004         /**
       
  3005         * @event drop:exit
       
  3006         * @description Fires when a drag element exits this target.
       
  3007         * @bubbles DDM
       
  3008         * @type {Event.Custom}
       
  3009         */
       
  3010         EV_DROP_EXIT = 'drop:exit',
       
  3011 
       
  3012         /**
       
  3013         * @event drop:hit
       
  3014         * @description Fires when a draggable node is dropped on this Drop Target. (Fired from dd-ddm-drop)
       
  3015         * @bubbles DDM
       
  3016         * @type {Event.Custom}
       
  3017         */
       
  3018         
       
  3019 
       
  3020     Drop = function() {
       
  3021         this._lazyAddAttrs = false;
       
  3022         Drop.superclass.constructor.apply(this, arguments);
       
  3023 
       
  3024 
       
  3025         //DD init speed up.
       
  3026         Y.on('domready', Y.bind(function() {
       
  3027             Y.later(100, this, this._createShim);
       
  3028         }, this));
       
  3029         DDM._regTarget(this);
       
  3030 
       
  3031         /* TODO
       
  3032         if (Dom.getStyle(this.el, 'position') == 'fixed') {
       
  3033             Event.on(window, 'scroll', function() {
       
  3034                 this.activateShim();
       
  3035             }, this, true);
       
  3036         }
       
  3037         */
       
  3038     };
       
  3039 
       
  3040     Drop.NAME = 'drop';
       
  3041 
       
  3042     Drop.ATTRS = {
       
  3043         /**
       
  3044         * @attribute node
       
  3045         * @description Y.Node instanace to use as the element to make a Drop Target
       
  3046         * @type Node
       
  3047         */        
       
  3048         node: {
       
  3049             setter: function(node) {
       
  3050                 var n = Y.Node.get(node);
       
  3051                 if (!n) {
       
  3052                     Y.error('DD.Drop: Invalid Node Given: ' + node);
       
  3053                 }
       
  3054                 return n;               
       
  3055             }
       
  3056         },
       
  3057         /**
       
  3058         * @attribute groups
       
  3059         * @description Array of groups to add this drop into.
       
  3060         * @type Array
       
  3061         */        
       
  3062         groups: {
       
  3063             value: ['default'],
       
  3064             setter: function(g) {
       
  3065                 this._groups = {};
       
  3066                 Y.each(g, function(v, k) {
       
  3067                     this._groups[v] = true;
       
  3068                 }, this);
       
  3069                 return g;
       
  3070             }
       
  3071         },   
       
  3072         /**
       
  3073         * @attribute padding
       
  3074         * @description CSS style padding to make the Drop Target bigger than the node.
       
  3075         * @type String
       
  3076         */
       
  3077         padding: {
       
  3078             value: '0',
       
  3079             setter: function(p) {
       
  3080                 return DDM.cssSizestoObject(p);
       
  3081             }
       
  3082         },
       
  3083         /**
       
  3084         * @attribute lock
       
  3085         * @description Set to lock this drop element.
       
  3086         * @type Boolean
       
  3087         */        
       
  3088         lock: {
       
  3089             value: false,
       
  3090             setter: function(lock) {
       
  3091                 if (lock) {
       
  3092                     this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-locked');
       
  3093                 } else {
       
  3094                     this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-locked');
       
  3095                 }
       
  3096                 return lock;
       
  3097             }
       
  3098         },
       
  3099         /**
       
  3100         * @attribute bubbles
       
  3101         * @description Controls the default bubble parent for this Drop instance. Default: Y.DD.DDM. Set to false to disable bubbling.
       
  3102         * @type Object
       
  3103         */
       
  3104         bubbles: {
       
  3105             writeOnce: true,
       
  3106             value: Y.DD.DDM
       
  3107         }
       
  3108     };
       
  3109 
       
  3110     Y.extend(Drop, Y.Base, {
       
  3111         /**
       
  3112         * @private
       
  3113         * @method _createEvents
       
  3114         * @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
       
  3115         */
       
  3116         _createEvents: function() {
       
  3117             
       
  3118             var ev = [
       
  3119                 EV_DROP_OVER,
       
  3120                 EV_DROP_ENTER,
       
  3121                 EV_DROP_EXIT,
       
  3122                 'drop:hit'
       
  3123             ];
       
  3124 
       
  3125             Y.each(ev, function(v, k) {
       
  3126                 this.publish(v, {
       
  3127                     type: v,
       
  3128                     emitFacade: true,
       
  3129                     preventable: false,
       
  3130                     bubbles: true,
       
  3131                     queuable: false,
       
  3132                     prefix: 'drop'
       
  3133                 });
       
  3134             }, this);
       
  3135 
       
  3136             if (this.get('bubbles')) {
       
  3137                 this.addTarget(this.get('bubbles'));
       
  3138             }
       
  3139             
       
  3140         },
       
  3141         /**
       
  3142         * @private
       
  3143         * @property _valid
       
  3144         * @description Flag for determining if the target is valid in this operation.
       
  3145         * @type Boolean
       
  3146         */
       
  3147         _valid: null,
       
  3148         /**
       
  3149         * @private
       
  3150         * @property _groups
       
  3151         * @description The groups this target belongs to.
       
  3152         * @type Array
       
  3153         */
       
  3154         _groups: null,
       
  3155         /**
       
  3156         * @property shim
       
  3157         * @description Node reference to the targets shim
       
  3158         * @type {Object}
       
  3159         */
       
  3160         shim: null,
       
  3161         /**
       
  3162         * @property region
       
  3163         * @description A region object associated with this target, used for checking regions while dragging.
       
  3164         * @type Object
       
  3165         */
       
  3166         region: null,
       
  3167         /**
       
  3168         * @property overTarget
       
  3169         * @description This flag is tripped when a drag element is over this target.
       
  3170         * @type Boolean
       
  3171         */
       
  3172         overTarget: null,
       
  3173         /**
       
  3174         * @method inGroup
       
  3175         * @description Check if this target is in one of the supplied groups.
       
  3176         * @param {Array} groups The groups to check against
       
  3177         * @return Boolean
       
  3178         */
       
  3179         inGroup: function(groups) {
       
  3180             this._valid = false;
       
  3181             var ret = false;
       
  3182             Y.each(groups, function(v, k) {
       
  3183                 if (this._groups[v]) {
       
  3184                     ret = true;
       
  3185                     this._valid = true;
       
  3186                 }
       
  3187             }, this);
       
  3188             return ret;
       
  3189         },
       
  3190         /**
       
  3191         * @private
       
  3192         * @method initializer
       
  3193         * @description Private lifecycle method
       
  3194         */
       
  3195         initializer: function() {
       
  3196             //this._createEvents();
       
  3197             Y.later(100, this, this._createEvents);
       
  3198 
       
  3199             var node = this.get(NODE), id;
       
  3200             if (!node.get('id')) {
       
  3201                 id = Y.stamp(node);
       
  3202                 node.set('id', id);
       
  3203             }
       
  3204             node.addClass(DDM.CSS_PREFIX + '-drop');
       
  3205             //Shouldn't have to do this..
       
  3206             this.set('groups', this.get('groups'));           
       
  3207         },
       
  3208         /**
       
  3209         * @private
       
  3210         * @method destructor
       
  3211         * @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
       
  3212         */
       
  3213         destructor: function() {
       
  3214             DDM._unregTarget(this);
       
  3215             if (this.shim) {
       
  3216                 this.shim.detachAll();
       
  3217                 this.shim.get('parentNode').removeChild(this.shim);
       
  3218                 this.shim = null;
       
  3219             }
       
  3220             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop');
       
  3221             this.detachAll();
       
  3222         },
       
  3223         /**
       
  3224         * @private
       
  3225         * @method _deactivateShim
       
  3226         * @description Removes classes from the target, resets some flags and sets the shims deactive position [-999, -999]
       
  3227         */
       
  3228         _deactivateShim: function() {
       
  3229             if (!this.shim) {
       
  3230                 return false;
       
  3231             }
       
  3232             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-active-valid');
       
  3233             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-active-invalid');
       
  3234             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-over');
       
  3235             this.shim.setStyles({
       
  3236                 top: '-999px',
       
  3237                 left: '-999px',
       
  3238                 zIndex: '2'
       
  3239             });
       
  3240             this.overTarget = false;
       
  3241         },
       
  3242         /**
       
  3243         * @private
       
  3244         * @method _activateShim
       
  3245         * @description Activates the shim and adds some interaction CSS classes
       
  3246         */
       
  3247         _activateShim: function() {
       
  3248             if (!DDM.activeDrag) {
       
  3249                 return false; //Nothing is dragging, no reason to activate.
       
  3250             }
       
  3251             if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
       
  3252                 return false;
       
  3253             }
       
  3254             if (this.get('lock')) {
       
  3255                 return false;
       
  3256             }
       
  3257             var node = this.get(NODE);
       
  3258             //TODO Visibility Check..
       
  3259             //if (this.inGroup(DDM.activeDrag.get('groups')) && this.get(NODE).isVisible()) {
       
  3260             if (this.inGroup(DDM.activeDrag.get('groups'))) {
       
  3261                 node.removeClass(DDM.CSS_PREFIX + '-drop-active-invalid');
       
  3262                 node.addClass(DDM.CSS_PREFIX + '-drop-active-valid');
       
  3263                 DDM._addValid(this);
       
  3264                 this.overTarget = false;
       
  3265                 this.sizeShim();
       
  3266             } else {
       
  3267                 DDM._removeValid(this);
       
  3268                 node.removeClass(DDM.CSS_PREFIX + '-drop-active-valid');
       
  3269                 node.addClass(DDM.CSS_PREFIX + '-drop-active-invalid');
       
  3270             }
       
  3271         },
       
  3272         /**
       
  3273         * @method sizeShim
       
  3274         * @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..
       
  3275         */
       
  3276         sizeShim: function() {
       
  3277             if (!DDM.activeDrag) {
       
  3278                 return false; //Nothing is dragging, no reason to activate.
       
  3279             }
       
  3280             if (this.get(NODE) === DDM.activeDrag.get(NODE)) {
       
  3281                 return false;
       
  3282             }
       
  3283             if (this.get('lock')) {
       
  3284                 return false;
       
  3285             }
       
  3286             if (!this.shim) {
       
  3287                 Y.later(100, this, this.sizeShim);
       
  3288                 return false;
       
  3289             }
       
  3290             var node = this.get(NODE),
       
  3291                 nh = node.get(OFFSET_HEIGHT),
       
  3292                 nw = node.get(OFFSET_WIDTH),
       
  3293                 xy = node.getXY(),
       
  3294                 p = this.get('padding'),
       
  3295                 dd, dH, dW;
       
  3296 
       
  3297 
       
  3298             //Apply padding
       
  3299             nw = nw + p.left + p.right;
       
  3300             nh = nh + p.top + p.bottom;
       
  3301             xy[0] = xy[0] - p.left;
       
  3302             xy[1] = xy[1] - p.top;
       
  3303             
       
  3304 
       
  3305             if (DDM.activeDrag.get('dragMode') === DDM.INTERSECT) {
       
  3306                 //Intersect Mode, make the shim bigger
       
  3307                 dd = DDM.activeDrag;
       
  3308                 dH = dd.get(NODE).get(OFFSET_HEIGHT);
       
  3309                 dW = dd.get(NODE).get(OFFSET_WIDTH);
       
  3310                 
       
  3311                 nh = (nh + dH);
       
  3312                 nw = (nw + dW);
       
  3313                 xy[0] = xy[0] - (dW - dd.deltaXY[0]);
       
  3314                 xy[1] = xy[1] - (dH - dd.deltaXY[1]);
       
  3315 
       
  3316             }
       
  3317             
       
  3318             //Set the style on the shim
       
  3319             this.shim.setStyles({
       
  3320                 height: nh + 'px',
       
  3321                 width: nw + 'px',
       
  3322                 top: xy[1] + 'px',
       
  3323                 left: xy[0] + 'px'
       
  3324             });
       
  3325             
       
  3326             //Create the region to be used by intersect when a drag node is over us.
       
  3327             this.region = {
       
  3328                 '0': xy[0], 
       
  3329                 '1': xy[1],
       
  3330                 area: 0,
       
  3331                 top: xy[1],
       
  3332                 right: xy[0] + nw,
       
  3333                 bottom: xy[1] + nh,
       
  3334                 left: xy[0]
       
  3335             };
       
  3336         },
       
  3337         /**
       
  3338         * @private
       
  3339         * @method _createShim
       
  3340         * @description Creates the Target shim and adds it to the DDM's playground..
       
  3341         */
       
  3342         _createShim: function() {
       
  3343             //No playground, defer
       
  3344             if (!DDM._pg) {
       
  3345                 Y.later(10, this, this._createShim);
       
  3346                 return;
       
  3347             }
       
  3348             //Shim already here, cancel
       
  3349             if (this.shim) {
       
  3350                 return;
       
  3351             }
       
  3352             var s = Y.Node.create('<div id="' + this.get(NODE).get('id') + '_shim"></div>');
       
  3353 
       
  3354             s.setStyles({
       
  3355                 height: this.get(NODE).get(OFFSET_HEIGHT) + 'px',
       
  3356                 width: this.get(NODE).get(OFFSET_WIDTH) + 'px',
       
  3357                 backgroundColor: 'yellow',
       
  3358                 opacity: '.5',
       
  3359                 zIndex: '1',
       
  3360                 overflow: 'hidden',
       
  3361                 top: '-900px',
       
  3362                 left: '-900px',
       
  3363                 position:  'absolute'
       
  3364             });
       
  3365             DDM._pg.appendChild(s);
       
  3366             this.shim = s;
       
  3367 
       
  3368             s.on('mouseover', Y.bind(this._handleOverEvent, this));
       
  3369             s.on('mouseout', Y.bind(this._handleOutEvent, this));
       
  3370         },
       
  3371         /**
       
  3372         * @private
       
  3373         * @method _handleOverTarget
       
  3374         * @description This handles the over target call made from this object or from the DDM
       
  3375         */
       
  3376         _handleTargetOver: function() {
       
  3377             if (DDM.isOverTarget(this)) {
       
  3378                 this.get(NODE).addClass(DDM.CSS_PREFIX + '-drop-over');
       
  3379                 DDM.activeDrop = this;
       
  3380                 DDM.otherDrops[this] = this;
       
  3381                 if (this.overTarget) {
       
  3382                     DDM.activeDrag.fire('drag:over', { drop: this, drag: DDM.activeDrag });
       
  3383                     this.fire(EV_DROP_OVER, { drop: this, drag: DDM.activeDrag });
       
  3384                 } else {
       
  3385                     this.overTarget = true;
       
  3386                     this.fire(EV_DROP_ENTER, { drop: this, drag: DDM.activeDrag });
       
  3387                     DDM.activeDrag.fire('drag:enter', { drop: this, drag: DDM.activeDrag });
       
  3388                     DDM.activeDrag.get(NODE).addClass(DDM.CSS_PREFIX + '-drag-over');
       
  3389                     //TODO - Is this needed??
       
  3390                     //DDM._handleTargetOver();
       
  3391                 }
       
  3392             } else {
       
  3393                 this._handleOut();
       
  3394             }
       
  3395         },
       
  3396         /**
       
  3397         * @private
       
  3398         * @method _handleOverEvent
       
  3399         * @description Handles the mouseover DOM event on the Target Shim
       
  3400         */
       
  3401         _handleOverEvent: function() {
       
  3402             this.shim.setStyle('zIndex', '999');
       
  3403             DDM._addActiveShim(this);
       
  3404         },
       
  3405         /**
       
  3406         * @private
       
  3407         * @method _handleOutEvent
       
  3408         * @description Handles the mouseout DOM event on the Target Shim
       
  3409         */
       
  3410         _handleOutEvent: function() {
       
  3411             this.shim.setStyle('zIndex', '1');
       
  3412             DDM._removeActiveShim(this);
       
  3413         },
       
  3414         /**
       
  3415         * @private
       
  3416         * @method _handleOut
       
  3417         * @description Handles out of target calls/checks
       
  3418         */
       
  3419         _handleOut: function(force) {
       
  3420             if (!DDM.isOverTarget(this) || force) {
       
  3421                 if (this.overTarget) {
       
  3422                     this.overTarget = false;
       
  3423                     if (!force) {
       
  3424                         DDM._removeActiveShim(this);
       
  3425                     }
       
  3426                     if (DDM.activeDrag) {
       
  3427                         this.get(NODE).removeClass(DDM.CSS_PREFIX + '-drop-over');
       
  3428                         DDM.activeDrag.get(NODE).removeClass(DDM.CSS_PREFIX + '-drag-over');
       
  3429                         this.fire(EV_DROP_EXIT);
       
  3430                         DDM.activeDrag.fire('drag:exit', { drop: this });
       
  3431                         delete DDM.otherDrops[this];
       
  3432                         //if (DDM.activeDrop === this) {
       
  3433                         //    DDM.activeDrop = null;
       
  3434                         //}
       
  3435                     }
       
  3436                 }
       
  3437             }
       
  3438         }
       
  3439     });
       
  3440 
       
  3441     Y.DD.Drop = Drop;
       
  3442 
       
  3443 
       
  3444 
       
  3445 
       
  3446 
       
  3447 }, '3.0.0b1' ,{requires:['dd-ddm-drop', 'dd-drag'], skinnable:false});
       
  3448 YUI.add('dd-drop-plugin', function(Y) {
       
  3449 
       
  3450 
       
  3451        /**
       
  3452         * This is a simple Drop plugin that can be attached to a Node via the plug method.
       
  3453         * @module dd
       
  3454         * @submodule dd-drop-plugin
       
  3455         */
       
  3456        /**
       
  3457         * This is a simple Drop plugin that can be attached to a Node via the plug method.
       
  3458         * @class Drop
       
  3459         * @extends DD.Drop
       
  3460         * @constructor
       
  3461         * @namespace Plugin
       
  3462         */
       
  3463 
       
  3464 
       
  3465         var Drop = function(config) {
       
  3466             config.node = config.host;
       
  3467             Drop.superclass.constructor.apply(this, arguments);
       
  3468         };
       
  3469         
       
  3470         /**
       
  3471         * @property NAME
       
  3472         * @description dd-drop-plugin
       
  3473         * @type {String}
       
  3474         */
       
  3475         Drop.NAME = "dd-drop-plugin";
       
  3476         /**
       
  3477         * @property NS
       
  3478         * @description The Drop instance will be placed on the Node instance under the drop namespace. It can be accessed via Node.drop;
       
  3479         * @type {String}
       
  3480         */
       
  3481         Drop.NS = "drop";
       
  3482 
       
  3483 
       
  3484         Y.extend(Drop, Y.DD.Drop);
       
  3485         Y.namespace('Plugin');
       
  3486         Y.Plugin.Drop = Drop;
       
  3487 
       
  3488 
       
  3489 
       
  3490 
       
  3491 
       
  3492 }, '3.0.0b1' ,{requires:['dd-drop'], skinnable:false});
       
  3493 
       
  3494 
       
  3495 YUI.add('dd', function(Y){}, '3.0.0b1' ,{use:['dd-ddm-base', 'dd-ddm', 'dd-ddm-drop', 'dd-drag', 'dd-proxy', 'dd-constrain', 'dd-plugin', 'dd-drop', 'dd-drop-plugin', 'dd-scroll'], skinnable:false});
       
  3496