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