src/cm/media/js/lib/yui/yui_3.0.0b1/build/dd/dd-drag-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-drag', function(Y) {
       
     9 
       
    10 
       
    11     /**
       
    12      * The Drag & Drop Utility allows you to create a draggable interface efficiently, buffering you from browser-level abnormalities and enabling you to focus on the interesting logic surrounding your particular implementation. This component enables you to create a variety of standard draggable objects with just a few lines of code and then, using its extensive API, add your own specific implementation logic.
       
    13      * @module dd
       
    14      * @submodule dd-drag
       
    15      */     
       
    16     /**
       
    17      * This class provides the ability to drag a Node.
       
    18      * @class Drag
       
    19      * @extends Base
       
    20      * @constructor
       
    21      * @namespace DD
       
    22      */
       
    23 
       
    24     var DDM = Y.DD.DDM,
       
    25         NODE = 'node',
       
    26         DRAGGING = 'dragging',
       
    27         DRAG_NODE = 'dragNode',
       
    28         OFFSET_HEIGHT = 'offsetHeight',
       
    29         OFFSET_WIDTH = 'offsetWidth',        
       
    30         MOUSE_UP = 'mouseup',
       
    31         MOUSE_DOWN = 'mousedown',
       
    32         DRAG_START = 'dragstart',
       
    33         /**
       
    34         * @event drag:mouseDown
       
    35         * @description Handles the mousedown DOM event, checks to see if you have a valid handle then starts the drag timers.
       
    36         * @preventable _defMouseDownFn
       
    37         * @param {Event.Facade} ev The mousedown event.
       
    38         * @bubbles DDM
       
    39         * @type {Event.Custom}
       
    40         */
       
    41         EV_MOUSE_DOWN = 'drag:mouseDown',
       
    42         /**
       
    43         * @event drag:afterMouseDown
       
    44         * @description Fires after the mousedown event has been cleared.
       
    45         * @param {Event.Facade} ev The mousedown event.
       
    46         * @bubbles DDM
       
    47         * @type {Event.Custom}
       
    48         */
       
    49         EV_AFTER_MOUSE_DOWN = 'drag:afterMouseDown',
       
    50         /**
       
    51         * @event drag:removeHandle
       
    52         * @description Fires after a handle is removed.
       
    53         * @bubbles DDM
       
    54         * @type {Event.Custom}
       
    55         */
       
    56         EV_REMOVE_HANDLE = 'drag:removeHandle',
       
    57         /**
       
    58         * @event drag:addHandle
       
    59         * @description Fires after a handle is added.
       
    60         * @bubbles DDM
       
    61         * @type {Event.Custom}
       
    62         */
       
    63         EV_ADD_HANDLE = 'drag:addHandle',
       
    64         /**
       
    65         * @event drag:removeInvalid
       
    66         * @description Fires after an invalid selector is removed.
       
    67         * @bubbles DDM
       
    68         * @type {Event.Custom}
       
    69         */
       
    70         EV_REMOVE_INVALID = 'drag:removeInvalid',
       
    71         /**
       
    72         * @event drag:addInvalid
       
    73         * @description Fires after an invalid selector is added.
       
    74         * @bubbles DDM
       
    75         * @type {Event.Custom}
       
    76         */
       
    77         EV_ADD_INVALID = 'drag:addInvalid',
       
    78         /**
       
    79         * @event drag:start
       
    80         * @description Fires at the start of a drag operation.
       
    81         * @bubbles DDM
       
    82         * @type {Event.Custom}
       
    83         */
       
    84         EV_START = 'drag:start',
       
    85         /**
       
    86         * @event drag:end
       
    87         * @description Fires at the end of a drag operation.
       
    88         * @bubbles DDM
       
    89         * @type {Event.Custom}
       
    90         */
       
    91         EV_END = 'drag:end',
       
    92         /**
       
    93         * @event drag:drag
       
    94         * @description Fires every mousemove during a drag operation.
       
    95         * @bubbles DDM
       
    96         * @type {Event.Custom}
       
    97         */
       
    98         EV_DRAG = 'drag:drag',
       
    99         /**
       
   100         * @event drag:align
       
   101         * @preventable _defAlignFn
       
   102         * @description Fires when this node is aligned.
       
   103         * @bubbles DDM
       
   104         * @type {Event.Custom}
       
   105         */
       
   106         EV_ALIGN = 'drag:align',
       
   107         /**
       
   108         * @event drag:over
       
   109         * @description Fires when this node is over a Drop Target. (Fired from dd-drop)
       
   110         * @bubbles DDM
       
   111         * @type {Event.Custom}
       
   112         */
       
   113         /**
       
   114         * @event drag:enter
       
   115         * @description Fires when this node enters a Drop Target. (Fired from dd-drop)
       
   116         * @bubbles DDM
       
   117         * @type {Event.Custom}
       
   118         */
       
   119         /**
       
   120         * @event drag:exit
       
   121         * @description Fires when this node exits a Drop Target. (Fired from dd-drop)
       
   122         * @bubbles DDM
       
   123         * @type {Event.Custom}
       
   124         */
       
   125         /**
       
   126         * @event drag:drophit
       
   127         * @description Fires when this node is dropped on a valid Drop Target. (Fired from dd-ddm-drop)
       
   128         * @bubbles DDM
       
   129         * @type {Event.Custom}
       
   130         */
       
   131         /**
       
   132         * @event drag:dropmiss
       
   133         * @description Fires when this node is dropped on an invalid Drop Target. (Fired from dd-ddm-drop)
       
   134         * @bubbles DDM
       
   135         * @type {Event.Custom}
       
   136         */
       
   137     
       
   138     Drag = function() {
       
   139         this._lazyAddAttrs = false;
       
   140         Drag.superclass.constructor.apply(this, arguments);
       
   141 
       
   142         DDM._regDrag(this);
       
   143     };
       
   144 
       
   145     Drag.NAME = 'drag';
       
   146 
       
   147     Drag.ATTRS = {
       
   148         /**
       
   149         * @attribute node
       
   150         * @description Y.Node instanace to use as the element to initiate a drag operation
       
   151         * @type Node
       
   152         */
       
   153         node: {
       
   154             setter: function(node) {
       
   155                 var n = Y.get(node);
       
   156                 if (!n) {
       
   157                     Y.error('DD.Drag: Invalid Node Given: ' + node);
       
   158                 } else {
       
   159                     n = n.item(0);
       
   160                 }
       
   161                 return n;
       
   162             }
       
   163         },
       
   164         /**
       
   165         * @attribute dragNode
       
   166         * @description Y.Node instanace to use as the draggable element, defaults to node
       
   167         * @type Node
       
   168         */
       
   169         dragNode: {
       
   170             setter: function(node) {
       
   171                 var n = Y.Node.get(node);
       
   172                 if (!n) {
       
   173                     Y.error('DD.Drag: Invalid dragNode Given: ' + node);
       
   174                 }
       
   175                 return n;
       
   176             }
       
   177         },
       
   178         /**
       
   179         * @attribute offsetNode
       
   180         * @description Offset the drag element by the difference in cursor position: default true
       
   181         * @type Boolean
       
   182         */
       
   183         offsetNode: {
       
   184             value: true
       
   185         },
       
   186         /**
       
   187         * @attribute clickPixelThresh
       
   188         * @description The number of pixels to move to start a drag operation, default is 3.
       
   189         * @type Number
       
   190         */
       
   191         clickPixelThresh: {
       
   192             value: DDM.get('clickPixelThresh')
       
   193         },
       
   194         /**
       
   195         * @attribute clickTimeThresh
       
   196         * @description The number of milliseconds a mousedown has to pass to start a drag operation, default is 1000.
       
   197         * @type Number
       
   198         */
       
   199         clickTimeThresh: {
       
   200             value: DDM.get('clickTimeThresh')
       
   201         },
       
   202         /**
       
   203         * @attribute lock
       
   204         * @description Set to lock this drag element so that it can't be dragged: default false.
       
   205         * @type Boolean
       
   206         */
       
   207         lock: {
       
   208             value: false,
       
   209             setter: function(lock) {
       
   210                 if (lock) {
       
   211                     this.get(NODE).addClass(DDM.CSS_PREFIX + '-locked');
       
   212                 } else {
       
   213                     this.get(NODE).removeClass(DDM.CSS_PREFIX + '-locked');
       
   214                 }
       
   215                 return lock;
       
   216             }
       
   217         },
       
   218         /**
       
   219         * @attribute data
       
   220         * @description A payload holder to store arbitrary data about this drag object, can be used to store any value.
       
   221         * @type Mixed
       
   222         */
       
   223         data: {
       
   224             value: false
       
   225         },
       
   226         /**
       
   227         * @attribute move
       
   228         * @description If this is false, the drag element will not move with the cursor: default true. Can be used to "resize" the element.
       
   229         * @type Boolean
       
   230         */
       
   231         move: {
       
   232             value: true
       
   233         },
       
   234         /**
       
   235         * @attribute useShim
       
   236         * @description Use the protective shim on all drag operations: default true. Only works with dd-ddm, not dd-ddm-base.
       
   237         * @type Boolean
       
   238         */
       
   239         useShim: {
       
   240             value: true
       
   241         },
       
   242         /**
       
   243         * @attribute activeHandle
       
   244         * @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.
       
   245         * @type Node
       
   246         */
       
   247         activeHandle: {
       
   248             value: false
       
   249         },
       
   250         /**
       
   251         * @attribute primaryButtonOnly
       
   252         * @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.
       
   253         * @type Boolean
       
   254         */
       
   255         primaryButtonOnly: {
       
   256             value: true
       
   257         },
       
   258         /**
       
   259         * @attribute dragging
       
   260         * @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.
       
   261         * @type Boolean
       
   262         */
       
   263         dragging: {
       
   264             value: false
       
   265         },
       
   266         parent: {
       
   267             value: false
       
   268         },
       
   269         /**
       
   270         * @attribute target
       
   271         * @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.
       
   272         * @type Boolean
       
   273         */
       
   274         target: {
       
   275             value: false,
       
   276             setter: function(config) {
       
   277                 this._handleTarget(config);
       
   278                 return config;
       
   279             }
       
   280         },
       
   281         /**
       
   282         * @attribute dragMode
       
   283         * @description This attribute only works if the dd-drop module is active. It will set the dragMode (point, intersect, strict) of this Drag instance.
       
   284         * @type String
       
   285         */
       
   286         dragMode: {
       
   287             value: null,
       
   288             setter: function(mode) {
       
   289                 return DDM._setDragMode(mode);
       
   290             }
       
   291         },
       
   292         /**
       
   293         * @attribute groups
       
   294         * @description Array of groups to add this drag into.
       
   295         * @type Array
       
   296         */
       
   297         groups: {
       
   298             value: ['default'],
       
   299             getter: function() {
       
   300                 if (!this._groups) {
       
   301                     this._groups = {};
       
   302                 }
       
   303                 var ret = [];
       
   304                 Y.each(this._groups, function(v, k) {
       
   305                     ret[ret.length] = k;
       
   306                 });
       
   307                 return ret;
       
   308             },
       
   309             setter: function(g) {
       
   310                 this._groups = {};
       
   311                 Y.each(g, function(v, k) {
       
   312                     this._groups[v] = true;
       
   313                 }, this);
       
   314                 return g;
       
   315             }
       
   316         },
       
   317         /**
       
   318         * @attribute handles
       
   319         * @description Array of valid handles to add. Adding something here will set all handles, even if previously added with addHandle
       
   320         * @type Array
       
   321         */
       
   322         handles: {
       
   323             value: null,
       
   324             setter: function(g) {
       
   325                 if (g) {
       
   326                     this._handles = {};
       
   327                     Y.each(g, function(v, k) {
       
   328                         this._handles[v] = true;
       
   329                     }, this);
       
   330                 } else {
       
   331                     this._handles = null;
       
   332                 }
       
   333                 return g;
       
   334             }
       
   335         },
       
   336         /**
       
   337         * @attribute bubbles
       
   338         * @description Controls the default bubble parent for this Drag instance. Default: Y.DD.DDM. Set to false to disable bubbling.
       
   339         * @type Object
       
   340         */
       
   341         bubbles: {
       
   342             writeOnce: true,
       
   343             value: Y.DD.DDM
       
   344         }
       
   345     };
       
   346 
       
   347     Y.extend(Drag, Y.Base, {
       
   348         /**
       
   349         * @method addToGroup
       
   350         * @description Add this Drag instance to a group, this should be used for on-the-fly group additions.
       
   351         * @param {String} g The group to add this Drag Instance to.
       
   352         * @return {Self}
       
   353         * @chainable
       
   354         */
       
   355         addToGroup: function(g) {
       
   356             this._groups[g] = true;
       
   357             DDM._activateTargets();
       
   358             return this;
       
   359         },
       
   360         /**
       
   361         * @method removeFromGroup
       
   362         * @description Remove this Drag instance from a group, this should be used for on-the-fly group removals.
       
   363         * @param {String} g The group to remove this Drag Instance from.
       
   364         * @return {Self}
       
   365         * @chainable
       
   366         */
       
   367         removeFromGroup: function(g) {
       
   368             delete this._groups[g];
       
   369             DDM._activateTargets();
       
   370             return this;
       
   371         },
       
   372         /**
       
   373         * @property target
       
   374         * @description This will be a reference to the Drop instance associated with this drag if the target: true config attribute is set..
       
   375         * @type {Object}
       
   376         */
       
   377         target: null,
       
   378         /**
       
   379         * @private
       
   380         * @method _handleTarget
       
   381         * @description Attribute handler for the target config attribute.
       
   382         * @param {Boolean/Object}
       
   383         * @return {Boolean/Object}
       
   384         */
       
   385         _handleTarget: function(config) {
       
   386             if (Y.DD.Drop) {
       
   387                 if (config === false) {
       
   388                     if (this.target) {
       
   389                         DDM._unregTarget(this.target);
       
   390                         this.target = null;
       
   391                     }
       
   392                     return false;
       
   393                 } else {
       
   394                     if (!Y.Lang.isObject(config)) {
       
   395                         config = {};
       
   396                     }
       
   397                     config.bubbles = ('bubbles' in config) ? config.bubbles : this.get('bubbles');
       
   398                     config.node = this.get(NODE);
       
   399                     config.groups = config.groups || this.get('groups');
       
   400                     this.target = new Y.DD.Drop(config);
       
   401                 }
       
   402             } else {
       
   403                 return false;
       
   404             }
       
   405         },
       
   406         /**
       
   407         * @private
       
   408         * @property _groups
       
   409         * @description Storage Array for the groups this drag belongs to.
       
   410         * @type {Array}
       
   411         */
       
   412         _groups: null,
       
   413         /**
       
   414         * @private
       
   415         * @method _createEvents
       
   416         * @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
       
   417         */
       
   418         _createEvents: function() {
       
   419             
       
   420             this.publish(EV_MOUSE_DOWN, {
       
   421                 defaultFn: this._defMouseDownFn,
       
   422                 queuable: false,
       
   423                 emitFacade: true,
       
   424                 bubbles: true,
       
   425                 prefix: 'drag'
       
   426             });
       
   427             
       
   428             this.publish(EV_ALIGN, {
       
   429                 defaultFn: this._defAlignFn,
       
   430                 queuable: false,
       
   431                 emitFacade: true,
       
   432                 bubbles: true,
       
   433                 prefix: 'drag'
       
   434             });
       
   435             
       
   436             this.publish(EV_DRAG, {
       
   437                 defaultFn: this._defDragFn,
       
   438                 queuable: false,
       
   439                 emitFacade: true,
       
   440                 bubbles: true,
       
   441                 prefix: 'drag'
       
   442             });
       
   443             
       
   444             this.publish(EV_END, {
       
   445                 preventedFn: this._prevEndFn,
       
   446                 queuable: false,
       
   447                 emitFacade: true,
       
   448                 bubbles: true,
       
   449                 prefix: 'drag'
       
   450             });
       
   451             
       
   452             var ev = [
       
   453                 EV_AFTER_MOUSE_DOWN,
       
   454                 EV_REMOVE_HANDLE,
       
   455                 EV_ADD_HANDLE,
       
   456                 EV_REMOVE_INVALID,
       
   457                 EV_ADD_INVALID,
       
   458                 EV_START,
       
   459                 'drag:drophit',
       
   460                 'drag:dropmiss',
       
   461                 'drag:over',
       
   462                 'drag:enter',
       
   463                 'drag:exit'
       
   464             ];
       
   465             
       
   466             Y.each(ev, function(v, k) {
       
   467                 this.publish(v, {
       
   468                     type: v,
       
   469                     emitFacade: true,
       
   470                     bubbles: true,
       
   471                     preventable: false,
       
   472                     queuable: false,
       
   473                     prefix: 'drag'
       
   474                 });
       
   475             }, this);
       
   476 
       
   477             if (this.get('bubbles')) {
       
   478                 this.addTarget(this.get('bubbles'));
       
   479             }
       
   480             
       
   481            
       
   482         },
       
   483         /**
       
   484         * @private
       
   485         * @property _ev_md
       
   486         * @description A private reference to the mousedown DOM event
       
   487         * @type {Event.Facade}
       
   488         */
       
   489         _ev_md: null,
       
   490         /**
       
   491         * @private
       
   492         * @property _startTime
       
   493         * @description The getTime of the mousedown event. Not used, just here in case someone wants/needs to use it.
       
   494         * @type Date
       
   495         */
       
   496         _startTime: null,
       
   497         /**
       
   498         * @private
       
   499         * @property _endTime
       
   500         * @description The getTime of the mouseup event. Not used, just here in case someone wants/needs to use it.
       
   501         * @type Date
       
   502         */
       
   503         _endTime: null,
       
   504         /**
       
   505         * @private
       
   506         * @property _handles
       
   507         * @description A private hash of the valid drag handles
       
   508         * @type {Object}
       
   509         */
       
   510         _handles: null,
       
   511         /**
       
   512         * @private
       
   513         * @property _invalids
       
   514         * @description A private hash of the invalid selector strings
       
   515         * @type {Object}
       
   516         */
       
   517         _invalids: null,
       
   518         /**
       
   519         * @private
       
   520         * @property _invalidsDefault
       
   521         * @description A private hash of the default invalid selector strings: {'textarea': true, 'input': true, 'a': true, 'button': true}
       
   522         * @type {Object}
       
   523         */
       
   524         _invalidsDefault: {'textarea': true, 'input': true, 'a': true, 'button': true},
       
   525         /**
       
   526         * @private
       
   527         * @property _dragThreshMet
       
   528         * @description Private flag to see if the drag threshhold was met
       
   529         * @type {Boolean}
       
   530         */
       
   531         _dragThreshMet: null,
       
   532         /**
       
   533         * @private
       
   534         * @property _fromTimeout
       
   535         * @description Flag to determine if the drag operation came from a timeout
       
   536         * @type {Boolean}
       
   537         */
       
   538         _fromTimeout: null,
       
   539         /**
       
   540         * @private
       
   541         * @property _clickTimeout
       
   542         * @description Holder for the setTimeout call
       
   543         * @type {Boolean}
       
   544         */
       
   545         _clickTimeout: null,
       
   546         /**
       
   547         * @property deltaXY
       
   548         * @description The offset of the mouse position to the element's position
       
   549         * @type {Array}
       
   550         */
       
   551         deltaXY: null,
       
   552         /**
       
   553         * @property startXY
       
   554         * @description The initial mouse position
       
   555         * @type {Array}
       
   556         */
       
   557         startXY: null,
       
   558         /**
       
   559         * @property nodeXY
       
   560         * @description The initial element position
       
   561         * @type {Array}
       
   562         */
       
   563         nodeXY: null,
       
   564         /**
       
   565         * @property lastXY
       
   566         * @description The position of the element as it's moving (for offset calculations)
       
   567         * @type {Array}
       
   568         */
       
   569         lastXY: null,
       
   570         /**
       
   571         * @property actXY
       
   572         * @description The xy that the node will be set to. Changing this will alter the position as it's dragged.
       
   573         * @type {Array}
       
   574         */
       
   575         actXY: null,
       
   576         /**
       
   577         * @property realXY
       
   578         * @description The real xy position of the node.
       
   579         * @type {Array}
       
   580         */
       
   581         realXY: null,
       
   582         /**
       
   583         * @property mouseXY
       
   584         * @description The XY coords of the mousemove
       
   585         * @type {Array}
       
   586         */
       
   587         mouseXY: null,
       
   588         /**
       
   589         * @property region
       
   590         * @description A region object associated with this drag, used for checking regions while dragging.
       
   591         * @type Object
       
   592         */
       
   593         region: null,       
       
   594         /**
       
   595         * @private
       
   596         * @method _handleMouseUp
       
   597         * @description Handler for the mouseup DOM event
       
   598         * @param {Event.Facade}
       
   599         */
       
   600         _handleMouseUp: function(ev) {
       
   601             this._fixIEMouseUp();
       
   602             if (DDM.activeDrag) {
       
   603                 DDM._end();
       
   604             }
       
   605         },
       
   606         /** 
       
   607         * @private
       
   608         * @method _fixDragStart
       
   609         * @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.
       
   610         */
       
   611         _fixDragStart: function(e) {
       
   612             e.preventDefault();
       
   613         },
       
   614         /** 
       
   615         * @private
       
   616         * @method _ieSelectFix
       
   617         * @description The function we use as the onselectstart handler when we start a drag in Internet Explorer
       
   618         */
       
   619         _ieSelectFix: function() {
       
   620             return false;
       
   621         },
       
   622         /** 
       
   623         * @private
       
   624         * @property _ieSelectBack
       
   625         * @description We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it.
       
   626         */
       
   627         _ieSelectBack: null,
       
   628         /**
       
   629         * @private
       
   630         * @method _fixIEMouseDown
       
   631         * @description This method copies the onselectstart listner on the document to the _ieSelectFix property
       
   632         */
       
   633         _fixIEMouseDown: function() {
       
   634             if (Y.UA.ie) {
       
   635                 this._ieSelectBack = Y.config.doc.body.onselectstart;
       
   636                 Y.config.doc.body.onselectstart = this._ieSelectFix;
       
   637             }           
       
   638         },
       
   639         /**
       
   640         * @private
       
   641         * @method _fixIEMouseUp
       
   642         * @description This method copies the _ieSelectFix property back to the onselectstart listner on the document.
       
   643         */
       
   644         _fixIEMouseUp: function() {
       
   645             if (Y.UA.ie) {
       
   646                 Y.config.doc.body.onselectstart = this._ieSelectBack;
       
   647             }           
       
   648         },
       
   649         /**
       
   650         * @private
       
   651         * @method _handleMouseDownEvent
       
   652         * @description Handler for the mousedown DOM event
       
   653         * @param {Event.Facade}
       
   654         */
       
   655         _handleMouseDownEvent: function(ev) {
       
   656             this.fire(EV_MOUSE_DOWN, { ev: ev });
       
   657         },
       
   658         /**
       
   659         * @private
       
   660         * @method _defMouseDownFn
       
   661         * @description Handler for the mousedown DOM event
       
   662         * @param {Event.Facade}
       
   663         */
       
   664         _defMouseDownFn: function(e) {
       
   665             var ev = e.ev;
       
   666             this._dragThreshMet = false;
       
   667             this._ev_md = ev;
       
   668             
       
   669             if (this.get('primaryButtonOnly') && ev.button > 1) {
       
   670                 return false;
       
   671             }
       
   672             if (this.validClick(ev)) {
       
   673                 this._fixIEMouseDown();
       
   674                 ev.halt();
       
   675                 this._setStartPosition([ev.pageX, ev.pageY]);
       
   676 
       
   677                 DDM.activeDrag = this;
       
   678                 
       
   679                 this._clickTimeout = Y.later(this.get('clickTimeThresh'), this, this._timeoutCheck);
       
   680             }
       
   681             this.fire(EV_AFTER_MOUSE_DOWN, { ev: ev });
       
   682         },
       
   683         /**
       
   684         * @method validClick
       
   685         * @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.
       
   686         * @param {Event.Facade}
       
   687         * @return {Boolean}
       
   688         */
       
   689         validClick: function(ev) {
       
   690             var r = false, n = false,
       
   691             tar = ev.target,
       
   692             hTest = null,
       
   693             els = null,
       
   694             set = false;
       
   695             if (this._handles) {
       
   696                 Y.each(this._handles, function(i, n) {
       
   697                     if (Y.Lang.isString(n)) {
       
   698                         //Am I this or am I inside this
       
   699                         if (tar.test(n + ', ' + n + ' *') && !hTest) {
       
   700                             hTest = n;
       
   701                             r = true;
       
   702                         }
       
   703                     }
       
   704                 });
       
   705             } else {
       
   706                 n = this.get(NODE)
       
   707                 if (n.contains(tar) || n.compareTo(tar)) {
       
   708                     r = true;
       
   709                 }
       
   710             }
       
   711             if (r) {
       
   712                 if (this._invalids) {
       
   713                     Y.each(this._invalids, function(i, n) {
       
   714                         if (Y.Lang.isString(n)) {
       
   715                             //Am I this or am I inside this
       
   716                             if (tar.test(n + ', ' + n + ' *')) {
       
   717                                 r = false;
       
   718                             }
       
   719                         }
       
   720                     });
       
   721                 }
       
   722             }
       
   723             if (r) {
       
   724                 if (hTest) {
       
   725                     els = ev.currentTarget.queryAll(hTest);
       
   726                     set = false;
       
   727                     els.each(function(n, i) {
       
   728                         if ((n.contains(tar) || n.compareTo(tar)) && !set) {
       
   729                             set = true;
       
   730                             this.set('activeHandle', n);
       
   731                         }
       
   732                     }, this);
       
   733                 } else {
       
   734                     this.set('activeHandle', this.get(NODE));
       
   735                 }
       
   736             }
       
   737             return r;
       
   738         },
       
   739         /**
       
   740         * @private
       
   741         * @method _setStartPosition
       
   742         * @description Sets the current position of the Element and calculates the offset
       
   743         * @param {Array} xy The XY coords to set the position to.
       
   744         */
       
   745         _setStartPosition: function(xy) {
       
   746             this.startXY = xy;
       
   747             
       
   748             this.nodeXY = this.lastXY = this.realXY = this.get(NODE).getXY();
       
   749 
       
   750             if (this.get('offsetNode')) {
       
   751                 this.deltaXY = [(this.startXY[0] - this.nodeXY[0]), (this.startXY[1] - this.nodeXY[1])];
       
   752             } else {
       
   753                 this.deltaXY = [0, 0];
       
   754             }
       
   755         },
       
   756         /**
       
   757         * @private
       
   758         * @method _timeoutCheck
       
   759         * @description The method passed to setTimeout to determine if the clickTimeThreshold was met.
       
   760         */
       
   761         _timeoutCheck: function() {
       
   762             if (!this.get('lock') && !this._dragThreshMet) {
       
   763                 this._fromTimeout = this._dragThreshMet = true;
       
   764                 this.start();
       
   765                 this._alignNode([this._ev_md.pageX, this._ev_md.pageY], true);
       
   766             }
       
   767         },
       
   768         /**
       
   769         * @method removeHandle
       
   770         * @description Remove a Selector added by addHandle
       
   771         * @param {String} str The selector for the handle to be removed. 
       
   772         * @return {Self}
       
   773         * @chainable
       
   774         */
       
   775         removeHandle: function(str) {
       
   776             if (this._handles[str]) {
       
   777                 delete this._handles[str];
       
   778                 this.fire(EV_REMOVE_HANDLE, { handle: str });
       
   779             }
       
   780             return this;
       
   781         },
       
   782         /**
       
   783         * @method addHandle
       
   784         * @description Add a handle to a drag element. Drag only initiates when a mousedown happens on this element.
       
   785         * @param {String} str The selector to test for a valid handle. Must be a child of the element.
       
   786         * @return {Self}
       
   787         * @chainable
       
   788         */
       
   789         addHandle: function(str) {
       
   790             if (!this._handles) {
       
   791                 this._handles = {};
       
   792             }
       
   793             if (Y.Lang.isString(str)) {
       
   794                 this._handles[str] = true;
       
   795                 this.fire(EV_ADD_HANDLE, { handle: str });
       
   796             }
       
   797             return this;
       
   798         },
       
   799         /**
       
   800         * @method removeInvalid
       
   801         * @description Remove an invalid handle added by addInvalid
       
   802         * @param {String} str The invalid handle to remove from the internal list.
       
   803         * @return {Self}
       
   804         * @chainable
       
   805         */
       
   806         removeInvalid: function(str) {
       
   807             if (this._invalids[str]) {
       
   808                 this._invalids[str] = null;
       
   809                 delete this._invalids[str];
       
   810                 this.fire(EV_REMOVE_INVALID, { handle: str });
       
   811             }
       
   812             return this;
       
   813         },
       
   814         /**
       
   815         * @method addInvalid
       
   816         * @description Add a selector string to test the handle against. If the test passes the drag operation will not continue.
       
   817         * @param {String} str The selector to test against to determine if this is an invalid drag handle.
       
   818         * @return {Self}
       
   819         * @chainable
       
   820         */
       
   821         addInvalid: function(str) {
       
   822             if (Y.Lang.isString(str)) {
       
   823                 this._invalids[str] = true;
       
   824                 this.fire(EV_ADD_INVALID, { handle: str });
       
   825             }
       
   826             return this;
       
   827         },
       
   828         /**
       
   829         * @private
       
   830         * @method initializer
       
   831         * @description Internal init handler
       
   832         */
       
   833         initializer: function() {
       
   834             this.get(NODE).dd = this;
       
   835 
       
   836             if (!this.get(NODE).get('id')) {
       
   837                 var id = Y.stamp(this.get(NODE));
       
   838                 this.get(NODE).set('id', id);
       
   839             }
       
   840 
       
   841             this.actXY = [];
       
   842             
       
   843             this._invalids = Y.clone(this._invalidsDefault, true);
       
   844 
       
   845             this._createEvents();
       
   846             
       
   847             if (!this.get(DRAG_NODE)) {
       
   848                 this.set(DRAG_NODE, this.get(NODE));
       
   849             }
       
   850             this._prep();
       
   851             this._dragThreshMet = false;
       
   852             //Shouldn't have to do this..
       
   853             this.set('groups', this.get('groups'));
       
   854         },
       
   855         /**
       
   856         * @private
       
   857         * @method _prep
       
   858         * @description Attach event listners and add classname
       
   859         */
       
   860         _prep: function() {
       
   861             var node = this.get(NODE);
       
   862             node.addClass(DDM.CSS_PREFIX + '-draggable');
       
   863             node.on(MOUSE_DOWN, Y.bind(this._handleMouseDownEvent, this));
       
   864             node.on(MOUSE_UP, Y.bind(this._handleMouseUp, this));
       
   865             node.on(DRAG_START, Y.bind(this._fixDragStart, this));
       
   866         },
       
   867         /**
       
   868         * @private
       
   869         * @method _unprep
       
   870         * @description Detach event listeners and remove classname
       
   871         */
       
   872         _unprep: function() {
       
   873             var node = this.get(NODE);
       
   874             node.removeClass(DDM.CSS_PREFIX + '-draggable');
       
   875             node.detachAll();
       
   876         },
       
   877         /**
       
   878         * @method start
       
   879         * @description Starts the drag operation
       
   880         * @return {Self}
       
   881         * @chainable
       
   882         */
       
   883         start: function() {
       
   884             if (!this.get('lock') && !this.get(DRAGGING)) {
       
   885                 var node = this.get(NODE), ow = node.get(OFFSET_WIDTH), oh = node.get(OFFSET_HEIGHT);
       
   886                 this._startTime = (new Date()).getTime();
       
   887 
       
   888                 DDM._start(this.deltaXY, [oh, ow]);
       
   889                 node.addClass(DDM.CSS_PREFIX + '-dragging');
       
   890                 this.fire(EV_START, {
       
   891                     pageX: this.nodeXY[0],
       
   892                     pageY: this.nodeXY[1],
       
   893                     startTime: this._startTime
       
   894                 });
       
   895                 var xy = this.nodeXY;
       
   896 
       
   897                 
       
   898                 this.region = {
       
   899                     '0': xy[0], 
       
   900                     '1': xy[1],
       
   901                     area: 0,
       
   902                     top: xy[1],
       
   903                     right: xy[0] + ow,
       
   904                     bottom: xy[1] + oh,
       
   905                     left: xy[0]
       
   906                 };
       
   907                 this.set(DRAGGING, true);
       
   908             }
       
   909             return this;
       
   910         },
       
   911         /**
       
   912         * @method end
       
   913         * @description Ends the drag operation
       
   914         * @return {Self}
       
   915         * @chainable
       
   916         */
       
   917         end: function() {
       
   918             this._endTime = (new Date()).getTime();
       
   919             if (this._clickTimeout) {
       
   920                 this._clickTimeout.cancel();
       
   921             }
       
   922             this._dragThreshMet = false;
       
   923             this._fromTimeout = false;
       
   924             if (!this.get('lock') && this.get(DRAGGING)) {
       
   925                 this.fire(EV_END, {
       
   926                     pageX: this.lastXY[0],
       
   927                     pageY: this.lastXY[1],
       
   928                     startTime: this._startTime,
       
   929                     endTime: this._endTime
       
   930                 });
       
   931             }
       
   932             this.get(NODE).removeClass(DDM.CSS_PREFIX + '-dragging');
       
   933             this.set(DRAGGING, false);
       
   934             this.deltaXY = [0, 0];
       
   935 
       
   936             return this;
       
   937         },
       
   938         /**
       
   939         * @private
       
   940         * @method _prevEndFn
       
   941         * @description Handler for preventing the drag:end event. It will reset the node back to it's start position
       
   942         */
       
   943         _prevEndFn: function(e) {
       
   944             //Bug #1852577
       
   945             this.get(DRAG_NODE).setXY(this.nodeXY);
       
   946         },
       
   947         /**
       
   948         * @private
       
   949         * @method _align
       
   950         * @description Calculates the offsets and set's the XY that the element will move to.
       
   951         * @param {Array} xy The xy coords to align with.
       
   952         */
       
   953         _align: function(xy) {
       
   954             this.fire(EV_ALIGN, {pageX: xy[0], pageY: xy[1] });
       
   955         },
       
   956         /**
       
   957         * @private
       
   958         * @method _defAlignFn
       
   959         * @description Calculates the offsets and set's the XY that the element will move to.
       
   960         * @param {Event.Facade} e The drag:align event.
       
   961         */
       
   962         _defAlignFn: function(e) {
       
   963             this.actXY = [e.pageX - this.deltaXY[0], e.pageY - this.deltaXY[1]];
       
   964         },
       
   965         /**
       
   966         * @private
       
   967         * @method _alignNode
       
   968         * @description This method performs the alignment before the element move.
       
   969         * @param {Array} eXY The XY to move the element to, usually comes from the mousemove DOM event.
       
   970         */
       
   971         _alignNode: function(eXY) {
       
   972             this._align(eXY);
       
   973             this._moveNode();
       
   974         },
       
   975         /**
       
   976         * @private
       
   977         * @method _moveNode
       
   978         * @description This method performs the actual element move.
       
   979         */
       
   980         _moveNode: function(scroll) {
       
   981             //if (!this.get(DRAGGING)) {
       
   982             //    return;
       
   983             //}
       
   984             var diffXY = [], diffXY2 = [], startXY = this.nodeXY, xy = this.actXY;
       
   985 
       
   986             diffXY[0] = (xy[0] - this.lastXY[0]);
       
   987             diffXY[1] = (xy[1] - this.lastXY[1]);
       
   988 
       
   989             diffXY2[0] = (xy[0] - this.nodeXY[0]);
       
   990             diffXY2[1] = (xy[1] - this.nodeXY[1]);
       
   991 
       
   992 
       
   993             this.region = {
       
   994                 '0': xy[0], 
       
   995                 '1': xy[1],
       
   996                 area: 0,
       
   997                 top: xy[1],
       
   998                 right: xy[0] + this.get(DRAG_NODE).get(OFFSET_WIDTH),
       
   999                 bottom: xy[1] + this.get(DRAG_NODE).get(OFFSET_HEIGHT),
       
  1000                 left: xy[0]
       
  1001             };
       
  1002 
       
  1003             this.fire(EV_DRAG, {
       
  1004                 pageX: xy[0],
       
  1005                 pageY: xy[1],
       
  1006                 scroll: scroll,
       
  1007                 info: {
       
  1008                     start: startXY,
       
  1009                     xy: xy,
       
  1010                     delta: diffXY,
       
  1011                     offset: diffXY2
       
  1012                 } 
       
  1013             });
       
  1014             
       
  1015             this.lastXY = xy;
       
  1016         },
       
  1017         /**
       
  1018         * @private
       
  1019         * @method _defDragFn
       
  1020         * @description Default function for drag:drag. Fired from _moveNode.
       
  1021         * @param {Event.Facade} ev The drag:drag event
       
  1022         */
       
  1023         _defDragFn: function(e) {
       
  1024             if (this.get('move')) {
       
  1025                 if (e.scroll) {
       
  1026                     e.scroll.node.set('scrollTop', e.scroll.top);
       
  1027                     e.scroll.node.set('scrollLeft', e.scroll.left);
       
  1028                 }
       
  1029                 this.get(DRAG_NODE).setXY([e.pageX, e.pageY]);
       
  1030                 this.realXY = [e.pageX, e.pageY];
       
  1031             }
       
  1032         },
       
  1033         /**
       
  1034         * @private
       
  1035         * @method _move
       
  1036         * @description Fired from DragDropMgr (DDM) on mousemove.
       
  1037         * @param {Event.Facade} ev The mousemove DOM event
       
  1038         */
       
  1039         _move: function(ev) {
       
  1040             if (this.get('lock')) {
       
  1041                 return false;
       
  1042             } else {
       
  1043                 this.mouseXY = [ev.pageX, ev.pageY];
       
  1044                 if (!this._dragThreshMet) {
       
  1045                     var diffX = Math.abs(this.startXY[0] - ev.pageX),
       
  1046                     diffY = Math.abs(this.startXY[1] - ev.pageY);
       
  1047                     if (diffX > this.get('clickPixelThresh') || diffY > this.get('clickPixelThresh')) {
       
  1048                         this._dragThreshMet = true;
       
  1049                         this.start();
       
  1050                         this._alignNode([ev.pageX, ev.pageY]);
       
  1051                     }
       
  1052                 } else {
       
  1053                     if (this._clickTimeout) {
       
  1054                         this._clickTimeout.cancel();
       
  1055                     }
       
  1056                     this._alignNode([ev.pageX, ev.pageY]);
       
  1057                 }
       
  1058             }
       
  1059         },
       
  1060         /**
       
  1061         * @method stopDrag
       
  1062         * @description Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag.
       
  1063         * @return {Self}
       
  1064         * @chainable
       
  1065         */
       
  1066         stopDrag: function() {
       
  1067             if (this.get(DRAGGING)) {
       
  1068                 DDM._end();
       
  1069             }
       
  1070             return this;
       
  1071         },
       
  1072         /**
       
  1073         * @private
       
  1074         * @method destructor
       
  1075         * @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
       
  1076         */
       
  1077         destructor: function() {
       
  1078             this._unprep();
       
  1079             this.detachAll();
       
  1080             if (this.target) {
       
  1081                 this.target.destroy();
       
  1082             }
       
  1083             DDM._unregDrag(this);
       
  1084         }
       
  1085     });
       
  1086     Y.namespace('DD');    
       
  1087     Y.DD.Drag = Drag;
       
  1088 
       
  1089 
       
  1090 
       
  1091 
       
  1092 
       
  1093 }, '3.0.0b1' ,{requires:['dd-ddm-base'], skinnable:false});