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