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