DDCore.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:92k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.0.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. /*
  8.  * These classes are derivatives of the similarly named classes in the YUI Library.
  9.  * The original license:
  10.  * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
  11.  * Code licensed under the BSD License:
  12.  * http://developer.yahoo.net/yui/license.txt
  13.  */
  14. (function() {
  15. var Event=Ext.EventManager;
  16. var Dom=Ext.lib.Dom;
  17. /**
  18.  * @class Ext.dd.DragDrop
  19.  * Defines the interface and base operation of items that that can be
  20.  * dragged or can be drop targets.  It was designed to be extended, overriding
  21.  * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
  22.  * Up to three html elements can be associated with a DragDrop instance:
  23.  * <ul>
  24.  * <li>linked element: the element that is passed into the constructor.
  25.  * This is the element which defines the boundaries for interaction with
  26.  * other DragDrop objects.</li>
  27.  * <li>handle element(s): The drag operation only occurs if the element that
  28.  * was clicked matches a handle element.  By default this is the linked
  29.  * element, but there are times that you will want only a portion of the
  30.  * linked element to initiate the drag operation, and the setHandleElId()
  31.  * method provides a way to define this.</li>
  32.  * <li>drag element: this represents the element that would be moved along
  33.  * with the cursor during a drag operation.  By default, this is the linked
  34.  * element itself as in {@link Ext.dd.DD}.  setDragElId() lets you define
  35.  * a separate element that would be moved, as in {@link Ext.dd.DDProxy}.
  36.  * </li>
  37.  * </ul>
  38.  * This class should not be instantiated until the onload event to ensure that
  39.  * the associated elements are available.
  40.  * The following would define a DragDrop obj that would interact with any
  41.  * other DragDrop obj in the "group1" group:
  42.  * <pre>
  43.  *  dd = new Ext.dd.DragDrop("div1", "group1");
  44.  * </pre>
  45.  * Since none of the event handlers have been implemented, nothing would
  46.  * actually happen if you were to run the code above.  Normally you would
  47.  * override this class or one of the default implementations, but you can
  48.  * also override the methods you want on an instance of the class...
  49.  * <pre>
  50.  *  dd.onDragDrop = function(e, id) {
  51.  *  &nbsp;&nbsp;alert("dd was dropped on " + id);
  52.  *  }
  53.  * </pre>
  54.  * @constructor
  55.  * @param {String} id of the element that is linked to this instance
  56.  * @param {String} sGroup the group of related DragDrop objects
  57.  * @param {object} config an object containing configurable attributes
  58.  *                Valid properties for DragDrop:
  59.  *                    padding, isTarget, maintainOffset, primaryButtonOnly
  60.  */
  61. Ext.dd.DragDrop = function(id, sGroup, config) {
  62.     if(id) {
  63.         this.init(id, sGroup, config);
  64.     }
  65. };
  66. Ext.dd.DragDrop.prototype = {
  67.     /**
  68.      * Set to false to enable a DragDrop object to fire drag events while dragging
  69.      * over its own Element. Defaults to true - DragDrop objects do not by default
  70.      * fire drag events to themselves.
  71.      * @property ignoreSelf
  72.      * @type Boolean
  73.      */
  74.     /**
  75.      * The id of the element associated with this object.  This is what we
  76.      * refer to as the "linked element" because the size and position of
  77.      * this element is used to determine when the drag and drop objects have
  78.      * interacted.
  79.      * @property id
  80.      * @type String
  81.      */
  82.     id: null,
  83.     /**
  84.      * Configuration attributes passed into the constructor
  85.      * @property config
  86.      * @type object
  87.      */
  88.     config: null,
  89.     /**
  90.      * The id of the element that will be dragged.  By default this is same
  91.      * as the linked element , but could be changed to another element. Ex:
  92.      * Ext.dd.DDProxy
  93.      * @property dragElId
  94.      * @type String
  95.      * @private
  96.      */
  97.     dragElId: null,
  98.     /**
  99.      * The ID of the element that initiates the drag operation.  By default
  100.      * this is the linked element, but could be changed to be a child of this
  101.      * element.  This lets us do things like only starting the drag when the
  102.      * header element within the linked html element is clicked.
  103.      * @property handleElId
  104.      * @type String
  105.      * @private
  106.      */
  107.     handleElId: null,
  108.     /**
  109.      * An object who's property names identify HTML tags to be considered invalid as drag handles.
  110.      * A non-null property value identifies the tag as invalid. Defaults to the 
  111.      * following value which prevents drag operations from being initiated by &lt;a> elements:<pre><code>
  112. {
  113.     A: "A"
  114. }</code></pre>
  115.      * @property invalidHandleTypes
  116.      * @type Object
  117.      */
  118.     invalidHandleTypes: null,
  119.     /**
  120.      * An object who's property names identify the IDs of elements to be considered invalid as drag handles.
  121.      * A non-null property value identifies the ID as invalid. For example, to prevent
  122.      * dragging from being initiated on element ID "foo", use:<pre><code>
  123. {
  124.     foo: true
  125. }</code></pre>
  126.      * @property invalidHandleIds
  127.      * @type Object
  128.      */
  129.     invalidHandleIds: null,
  130.     /**
  131.      * An Array of CSS class names for elements to be considered in valid as drag handles.
  132.      * @property invalidHandleClasses
  133.      * @type Array
  134.      */
  135.     invalidHandleClasses: null,
  136.     /**
  137.      * The linked element's absolute X position at the time the drag was
  138.      * started
  139.      * @property startPageX
  140.      * @type int
  141.      * @private
  142.      */
  143.     startPageX: 0,
  144.     /**
  145.      * The linked element's absolute X position at the time the drag was
  146.      * started
  147.      * @property startPageY
  148.      * @type int
  149.      * @private
  150.      */
  151.     startPageY: 0,
  152.     /**
  153.      * The group defines a logical collection of DragDrop objects that are
  154.      * related.  Instances only get events when interacting with other
  155.      * DragDrop object in the same group.  This lets us define multiple
  156.      * groups using a single DragDrop subclass if we want.
  157.      * @property groups
  158.      * @type object An object in the format {'group1':true, 'group2':true}
  159.      */
  160.     groups: null,
  161.     /**
  162.      * Individual drag/drop instances can be locked.  This will prevent
  163.      * onmousedown start drag.
  164.      * @property locked
  165.      * @type boolean
  166.      * @private
  167.      */
  168.     locked: false,
  169.     /**
  170.      * Lock this instance
  171.      * @method lock
  172.      */
  173.     lock: function() { this.locked = true; },
  174.     /**
  175.      * When set to true, other DD objects in cooperating DDGroups do not receive
  176.      * notification events when this DD object is dragged over them. Defaults to false.
  177.      * @property moveOnly
  178.      * @type boolean
  179.      */
  180.     moveOnly: false,
  181.     /**
  182.      * Unlock this instace
  183.      * @method unlock
  184.      */
  185.     unlock: function() { this.locked = false; },
  186.     /**
  187.      * By default, all instances can be a drop target.  This can be disabled by
  188.      * setting isTarget to false.
  189.      * @property isTarget
  190.      * @type boolean
  191.      */
  192.     isTarget: true,
  193.     /**
  194.      * The padding configured for this drag and drop object for calculating
  195.      * the drop zone intersection with this object.
  196.      * @property padding
  197.      * @type int[] An array containing the 4 padding values: [top, right, bottom, left]
  198.      */
  199.     padding: null,
  200.     /**
  201.      * Cached reference to the linked element
  202.      * @property _domRef
  203.      * @private
  204.      */
  205.     _domRef: null,
  206.     /**
  207.      * Internal typeof flag
  208.      * @property __ygDragDrop
  209.      * @private
  210.      */
  211.     __ygDragDrop: true,
  212.     /**
  213.      * Set to true when horizontal contraints are applied
  214.      * @property constrainX
  215.      * @type boolean
  216.      * @private
  217.      */
  218.     constrainX: false,
  219.     /**
  220.      * Set to true when vertical contraints are applied
  221.      * @property constrainY
  222.      * @type boolean
  223.      * @private
  224.      */
  225.     constrainY: false,
  226.     /**
  227.      * The left constraint
  228.      * @property minX
  229.      * @type int
  230.      * @private
  231.      */
  232.     minX: 0,
  233.     /**
  234.      * The right constraint
  235.      * @property maxX
  236.      * @type int
  237.      * @private
  238.      */
  239.     maxX: 0,
  240.     /**
  241.      * The up constraint
  242.      * @property minY
  243.      * @type int
  244.      * @type int
  245.      * @private
  246.      */
  247.     minY: 0,
  248.     /**
  249.      * The down constraint
  250.      * @property maxY
  251.      * @type int
  252.      * @private
  253.      */
  254.     maxY: 0,
  255.     /**
  256.      * Maintain offsets when we resetconstraints.  Set to true when you want
  257.      * the position of the element relative to its parent to stay the same
  258.      * when the page changes
  259.      *
  260.      * @property maintainOffset
  261.      * @type boolean
  262.      */
  263.     maintainOffset: false,
  264.     /**
  265.      * Array of pixel locations the element will snap to if we specified a
  266.      * horizontal graduation/interval.  This array is generated automatically
  267.      * when you define a tick interval.
  268.      * @property xTicks
  269.      * @type int[]
  270.      */
  271.     xTicks: null,
  272.     /**
  273.      * Array of pixel locations the element will snap to if we specified a
  274.      * vertical graduation/interval.  This array is generated automatically
  275.      * when you define a tick interval.
  276.      * @property yTicks
  277.      * @type int[]
  278.      */
  279.     yTicks: null,
  280.     /**
  281.      * By default the drag and drop instance will only respond to the primary
  282.      * button click (left button for a right-handed mouse).  Set to true to
  283.      * allow drag and drop to start with any mouse click that is propogated
  284.      * by the browser
  285.      * @property primaryButtonOnly
  286.      * @type boolean
  287.      */
  288.     primaryButtonOnly: true,
  289.     /**
  290.      * The availabe property is false until the linked dom element is accessible.
  291.      * @property available
  292.      * @type boolean
  293.      */
  294.     available: false,
  295.     /**
  296.      * By default, drags can only be initiated if the mousedown occurs in the
  297.      * region the linked element is.  This is done in part to work around a
  298.      * bug in some browsers that mis-report the mousedown if the previous
  299.      * mouseup happened outside of the window.  This property is set to true
  300.      * if outer handles are defined.
  301.      *
  302.      * @property hasOuterHandles
  303.      * @type boolean
  304.      * @default false
  305.      */
  306.     hasOuterHandles: false,
  307.     /**
  308.      * Code that executes immediately before the startDrag event
  309.      * @method b4StartDrag
  310.      * @private
  311.      */
  312.     b4StartDrag: function(x, y) { },
  313.     /**
  314.      * Abstract method called after a drag/drop object is clicked
  315.      * and the drag or mousedown time thresholds have beeen met.
  316.      * @method startDrag
  317.      * @param {int} X click location
  318.      * @param {int} Y click location
  319.      */
  320.     startDrag: function(x, y) { /* override this */ },
  321.     /**
  322.      * Code that executes immediately before the onDrag event
  323.      * @method b4Drag
  324.      * @private
  325.      */
  326.     b4Drag: function(e) { },
  327.     /**
  328.      * Abstract method called during the onMouseMove event while dragging an
  329.      * object.
  330.      * @method onDrag
  331.      * @param {Event} e the mousemove event
  332.      */
  333.     onDrag: function(e) { /* override this */ },
  334.     /**
  335.      * Abstract method called when this element fist begins hovering over
  336.      * another DragDrop obj
  337.      * @method onDragEnter
  338.      * @param {Event} e the mousemove event
  339.      * @param {String|DragDrop[]} id In POINT mode, the element
  340.      * id this is hovering over.  In INTERSECT mode, an array of one or more
  341.      * dragdrop items being hovered over.
  342.      */
  343.     onDragEnter: function(e, id) { /* override this */ },
  344.     /**
  345.      * Code that executes immediately before the onDragOver event
  346.      * @method b4DragOver
  347.      * @private
  348.      */
  349.     b4DragOver: function(e) { },
  350.     /**
  351.      * Abstract method called when this element is hovering over another
  352.      * DragDrop obj
  353.      * @method onDragOver
  354.      * @param {Event} e the mousemove event
  355.      * @param {String|DragDrop[]} id In POINT mode, the element
  356.      * id this is hovering over.  In INTERSECT mode, an array of dd items
  357.      * being hovered over.
  358.      */
  359.     onDragOver: function(e, id) { /* override this */ },
  360.     /**
  361.      * Code that executes immediately before the onDragOut event
  362.      * @method b4DragOut
  363.      * @private
  364.      */
  365.     b4DragOut: function(e) { },
  366.     /**
  367.      * Abstract method called when we are no longer hovering over an element
  368.      * @method onDragOut
  369.      * @param {Event} e the mousemove event
  370.      * @param {String|DragDrop[]} id In POINT mode, the element
  371.      * id this was hovering over.  In INTERSECT mode, an array of dd items
  372.      * that the mouse is no longer over.
  373.      */
  374.     onDragOut: function(e, id) { /* override this */ },
  375.     /**
  376.      * Code that executes immediately before the onDragDrop event
  377.      * @method b4DragDrop
  378.      * @private
  379.      */
  380.     b4DragDrop: function(e) { },
  381.     /**
  382.      * Abstract method called when this item is dropped on another DragDrop
  383.      * obj
  384.      * @method onDragDrop
  385.      * @param {Event} e the mouseup event
  386.      * @param {String|DragDrop[]} id In POINT mode, the element
  387.      * id this was dropped on.  In INTERSECT mode, an array of dd items this
  388.      * was dropped on.
  389.      */
  390.     onDragDrop: function(e, id) { /* override this */ },
  391.     /**
  392.      * Abstract method called when this item is dropped on an area with no
  393.      * drop target
  394.      * @method onInvalidDrop
  395.      * @param {Event} e the mouseup event
  396.      */
  397.     onInvalidDrop: function(e) { /* override this */ },
  398.     /**
  399.      * Code that executes immediately before the endDrag event
  400.      * @method b4EndDrag
  401.      * @private
  402.      */
  403.     b4EndDrag: function(e) { },
  404.     /**
  405.      * Fired when we are done dragging the object
  406.      * @method endDrag
  407.      * @param {Event} e the mouseup event
  408.      */
  409.     endDrag: function(e) { /* override this */ },
  410.     /**
  411.      * Code executed immediately before the onMouseDown event
  412.      * @method b4MouseDown
  413.      * @param {Event} e the mousedown event
  414.      * @private
  415.      */
  416.     b4MouseDown: function(e) {  },
  417.     /**
  418.      * Event handler that fires when a drag/drop obj gets a mousedown
  419.      * @method onMouseDown
  420.      * @param {Event} e the mousedown event
  421.      */
  422.     onMouseDown: function(e) { /* override this */ },
  423.     /**
  424.      * Event handler that fires when a drag/drop obj gets a mouseup
  425.      * @method onMouseUp
  426.      * @param {Event} e the mouseup event
  427.      */
  428.     onMouseUp: function(e) { /* override this */ },
  429.     /**
  430.      * Override the onAvailable method to do what is needed after the initial
  431.      * position was determined.
  432.      * @method onAvailable
  433.      */
  434.     onAvailable: function () {
  435.     },
  436.     /**
  437.      * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
  438.      * @type Object
  439.      */
  440.     defaultPadding : {left:0, right:0, top:0, bottom:0},
  441.     /**
  442.      * Initializes the drag drop object's constraints to restrict movement to a certain element.
  443.  *
  444.  * Usage:
  445.  <pre><code>
  446.  var dd = new Ext.dd.DDProxy("dragDiv1", "proxytest",
  447.                 { dragElId: "existingProxyDiv" });
  448.  dd.startDrag = function(){
  449.      this.constrainTo("parent-id");
  450.  };
  451.  </code></pre>
  452.  * Or you can initalize it using the {@link Ext.Element} object:
  453.  <pre><code>
  454.  Ext.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
  455.      startDrag : function(){
  456.          this.constrainTo("parent-id");
  457.      }
  458.  });
  459.  </code></pre>
  460.      * @param {Mixed} constrainTo The element to constrain to.
  461.      * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
  462.      * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
  463.      * an object containing the sides to pad. For example: {right:10, bottom:10}
  464.      * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
  465.      */
  466.     constrainTo : function(constrainTo, pad, inContent){
  467.         if(typeof pad == "number"){
  468.             pad = {left: pad, right:pad, top:pad, bottom:pad};
  469.         }
  470.         pad = pad || this.defaultPadding;
  471.         var b = Ext.get(this.getEl()).getBox();
  472.         var ce = Ext.get(constrainTo);
  473.         var s = ce.getScroll();
  474.         var c, cd = ce.dom;
  475.         if(cd == document.body){
  476.             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
  477.         }else{
  478.             var xy = ce.getXY();
  479.             c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
  480.         }
  481.         var topSpace = b.y - c.y;
  482.         var leftSpace = b.x - c.x;
  483.         this.resetConstraints();
  484.         this.setXConstraint(leftSpace - (pad.left||0), // left
  485.                 c.width - leftSpace - b.width - (pad.right||0), //right
  486. this.xTickSize
  487.         );
  488.         this.setYConstraint(topSpace - (pad.top||0), //top
  489.                 c.height - topSpace - b.height - (pad.bottom||0), //bottom
  490. this.yTickSize
  491.         );
  492.     },
  493.     /**
  494.      * Returns a reference to the linked element
  495.      * @method getEl
  496.      * @return {HTMLElement} the html element
  497.      */
  498.     getEl: function() {
  499.         if (!this._domRef) {
  500.             this._domRef = Ext.getDom(this.id);
  501.         }
  502.         return this._domRef;
  503.     },
  504.     /**
  505.      * Returns a reference to the actual element to drag.  By default this is
  506.      * the same as the html element, but it can be assigned to another
  507.      * element. An example of this can be found in Ext.dd.DDProxy
  508.      * @method getDragEl
  509.      * @return {HTMLElement} the html element
  510.      */
  511.     getDragEl: function() {
  512.         return Ext.getDom(this.dragElId);
  513.     },
  514.     /**
  515.      * Sets up the DragDrop object.  Must be called in the constructor of any
  516.      * Ext.dd.DragDrop subclass
  517.      * @method init
  518.      * @param id the id of the linked element
  519.      * @param {String} sGroup the group of related items
  520.      * @param {object} config configuration attributes
  521.      */
  522.     init: function(id, sGroup, config) {
  523.         this.initTarget(id, sGroup, config);
  524.         Event.on(this.id, "mousedown", this.handleMouseDown, this);
  525.         // Event.on(this.id, "selectstart", Event.preventDefault);
  526.     },
  527.     /**
  528.      * Initializes Targeting functionality only... the object does not
  529.      * get a mousedown handler.
  530.      * @method initTarget
  531.      * @param id the id of the linked element
  532.      * @param {String} sGroup the group of related items
  533.      * @param {object} config configuration attributes
  534.      */
  535.     initTarget: function(id, sGroup, config) {
  536.         // configuration attributes
  537.         this.config = config || {};
  538.         // create a local reference to the drag and drop manager
  539.         this.DDM = Ext.dd.DDM;
  540.         // initialize the groups array
  541.         this.groups = {};
  542.         // assume that we have an element reference instead of an id if the
  543.         // parameter is not a string
  544.         if (typeof id !== "string") {
  545.             id = Ext.id(id);
  546.         }
  547.         // set the id
  548.         this.id = id;
  549.         // add to an interaction group
  550.         this.addToGroup((sGroup) ? sGroup : "default");
  551.         // We don't want to register this as the handle with the manager
  552.         // so we just set the id rather than calling the setter.
  553.         this.handleElId = id;
  554.         // the linked element is the element that gets dragged by default
  555.         this.setDragElId(id);
  556.         // by default, clicked anchors will not start drag operations.
  557.         this.invalidHandleTypes = { A: "A" };
  558.         this.invalidHandleIds = {};
  559.         this.invalidHandleClasses = [];
  560.         this.applyConfig();
  561.         this.handleOnAvailable();
  562.     },
  563.     /**
  564.      * Applies the configuration parameters that were passed into the constructor.
  565.      * This is supposed to happen at each level through the inheritance chain.  So
  566.      * a DDProxy implentation will execute apply config on DDProxy, DD, and
  567.      * DragDrop in order to get all of the parameters that are available in
  568.      * each object.
  569.      * @method applyConfig
  570.      */
  571.     applyConfig: function() {
  572.         // configurable properties:
  573.         //    padding, isTarget, maintainOffset, primaryButtonOnly
  574.         this.padding           = this.config.padding || [0, 0, 0, 0];
  575.         this.isTarget          = (this.config.isTarget !== false);
  576.         this.maintainOffset    = (this.config.maintainOffset);
  577.         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
  578.     },
  579.     /**
  580.      * Executed when the linked element is available
  581.      * @method handleOnAvailable
  582.      * @private
  583.      */
  584.     handleOnAvailable: function() {
  585.         this.available = true;
  586.         this.resetConstraints();
  587.         this.onAvailable();
  588.     },
  589.      /**
  590.      * Configures the padding for the target zone in px.  Effectively expands
  591.      * (or reduces) the virtual object size for targeting calculations.
  592.      * Supports css-style shorthand; if only one parameter is passed, all sides
  593.      * will have that padding, and if only two are passed, the top and bottom
  594.      * will have the first param, the left and right the second.
  595.      * @method setPadding
  596.      * @param {int} iTop    Top pad
  597.      * @param {int} iRight  Right pad
  598.      * @param {int} iBot    Bot pad
  599.      * @param {int} iLeft   Left pad
  600.      */
  601.     setPadding: function(iTop, iRight, iBot, iLeft) {
  602.         // this.padding = [iLeft, iRight, iTop, iBot];
  603.         if (!iRight && 0 !== iRight) {
  604.             this.padding = [iTop, iTop, iTop, iTop];
  605.         } else if (!iBot && 0 !== iBot) {
  606.             this.padding = [iTop, iRight, iTop, iRight];
  607.         } else {
  608.             this.padding = [iTop, iRight, iBot, iLeft];
  609.         }
  610.     },
  611.     /**
  612.      * Stores the initial placement of the linked element.
  613.      * @method setInitPosition
  614.      * @param {int} diffX   the X offset, default 0
  615.      * @param {int} diffY   the Y offset, default 0
  616.      */
  617.     setInitPosition: function(diffX, diffY) {
  618.         var el = this.getEl();
  619.         if (!this.DDM.verifyEl(el)) {
  620.             return;
  621.         }
  622.         var dx = diffX || 0;
  623.         var dy = diffY || 0;
  624.         var p = Dom.getXY( el );
  625.         this.initPageX = p[0] - dx;
  626.         this.initPageY = p[1] - dy;
  627.         this.lastPageX = p[0];
  628.         this.lastPageY = p[1];
  629.         this.setStartPosition(p);
  630.     },
  631.     /**
  632.      * Sets the start position of the element.  This is set when the obj
  633.      * is initialized, the reset when a drag is started.
  634.      * @method setStartPosition
  635.      * @param pos current position (from previous lookup)
  636.      * @private
  637.      */
  638.     setStartPosition: function(pos) {
  639.         var p = pos || Dom.getXY( this.getEl() );
  640.         this.deltaSetXY = null;
  641.         this.startPageX = p[0];
  642.         this.startPageY = p[1];
  643.     },
  644.     /**
  645.      * Add this instance to a group of related drag/drop objects.  All
  646.      * instances belong to at least one group, and can belong to as many
  647.      * groups as needed.
  648.      * @method addToGroup
  649.      * @param sGroup {string} the name of the group
  650.      */
  651.     addToGroup: function(sGroup) {
  652.         this.groups[sGroup] = true;
  653.         this.DDM.regDragDrop(this, sGroup);
  654.     },
  655.     /**
  656.      * Remove's this instance from the supplied interaction group
  657.      * @method removeFromGroup
  658.      * @param {string}  sGroup  The group to drop
  659.      */
  660.     removeFromGroup: function(sGroup) {
  661.         if (this.groups[sGroup]) {
  662.             delete this.groups[sGroup];
  663.         }
  664.         this.DDM.removeDDFromGroup(this, sGroup);
  665.     },
  666.     /**
  667.      * Allows you to specify that an element other than the linked element
  668.      * will be moved with the cursor during a drag
  669.      * @method setDragElId
  670.      * @param id {string} the id of the element that will be used to initiate the drag
  671.      */
  672.     setDragElId: function(id) {
  673.         this.dragElId = id;
  674.     },
  675.     /**
  676.      * Allows you to specify a child of the linked element that should be
  677.      * used to initiate the drag operation.  An example of this would be if
  678.      * you have a content div with text and links.  Clicking anywhere in the
  679.      * content area would normally start the drag operation.  Use this method
  680.      * to specify that an element inside of the content div is the element
  681.      * that starts the drag operation.
  682.      * @method setHandleElId
  683.      * @param id {string} the id of the element that will be used to
  684.      * initiate the drag.
  685.      */
  686.     setHandleElId: function(id) {
  687.         if (typeof id !== "string") {
  688.             id = Ext.id(id);
  689.         }
  690.         this.handleElId = id;
  691.         this.DDM.regHandle(this.id, id);
  692.     },
  693.     /**
  694.      * Allows you to set an element outside of the linked element as a drag
  695.      * handle
  696.      * @method setOuterHandleElId
  697.      * @param id the id of the element that will be used to initiate the drag
  698.      */
  699.     setOuterHandleElId: function(id) {
  700.         if (typeof id !== "string") {
  701.             id = Ext.id(id);
  702.         }
  703.         Event.on(id, "mousedown",
  704.                 this.handleMouseDown, this);
  705.         this.setHandleElId(id);
  706.         this.hasOuterHandles = true;
  707.     },
  708.     /**
  709.      * Remove all drag and drop hooks for this element
  710.      * @method unreg
  711.      */
  712.     unreg: function() {
  713.         Event.un(this.id, "mousedown",
  714.                 this.handleMouseDown);
  715.         this._domRef = null;
  716.         this.DDM._remove(this);
  717.     },
  718.     destroy : function(){
  719.         this.unreg();
  720.     },
  721.     /**
  722.      * Returns true if this instance is locked, or the drag drop mgr is locked
  723.      * (meaning that all drag/drop is disabled on the page.)
  724.      * @method isLocked
  725.      * @return {boolean} true if this obj or all drag/drop is locked, else
  726.      * false
  727.      */
  728.     isLocked: function() {
  729.         return (this.DDM.isLocked() || this.locked);
  730.     },
  731.     /**
  732.      * Fired when this object is clicked
  733.      * @method handleMouseDown
  734.      * @param {Event} e
  735.      * @param {Ext.dd.DragDrop} oDD the clicked dd object (this dd obj)
  736.      * @private
  737.      */
  738.     handleMouseDown: function(e, oDD){
  739.         if (this.primaryButtonOnly && e.button != 0) {
  740.             return;
  741.         }
  742.         if (this.isLocked()) {
  743.             return;
  744.         }
  745.         this.DDM.refreshCache(this.groups);
  746.         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
  747.         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
  748.         } else {
  749.             if (this.clickValidator(e)) {
  750.                 // set the initial element position
  751.                 this.setStartPosition();
  752.                 this.b4MouseDown(e);
  753.                 this.onMouseDown(e);
  754.                 this.DDM.handleMouseDown(e, this);
  755.                 this.DDM.stopEvent(e);
  756.             } else {
  757.             }
  758.         }
  759.     },
  760.     clickValidator: function(e) {
  761.         var target = e.getTarget();
  762.         return ( this.isValidHandleChild(target) &&
  763.                     (this.id == this.handleElId ||
  764.                         this.DDM.handleWasClicked(target, this.id)) );
  765.     },
  766.     /**
  767.      * Allows you to specify a tag name that should not start a drag operation
  768.      * when clicked.  This is designed to facilitate embedding links within a
  769.      * drag handle that do something other than start the drag.
  770.      * @method addInvalidHandleType
  771.      * @param {string} tagName the type of element to exclude
  772.      */
  773.     addInvalidHandleType: function(tagName) {
  774.         var type = tagName.toUpperCase();
  775.         this.invalidHandleTypes[type] = type;
  776.     },
  777.     /**
  778.      * Lets you to specify an element id for a child of a drag handle
  779.      * that should not initiate a drag
  780.      * @method addInvalidHandleId
  781.      * @param {string} id the element id of the element you wish to ignore
  782.      */
  783.     addInvalidHandleId: function(id) {
  784.         if (typeof id !== "string") {
  785.             id = Ext.id(id);
  786.         }
  787.         this.invalidHandleIds[id] = id;
  788.     },
  789.     /**
  790.      * Lets you specify a css class of elements that will not initiate a drag
  791.      * @method addInvalidHandleClass
  792.      * @param {string} cssClass the class of the elements you wish to ignore
  793.      */
  794.     addInvalidHandleClass: function(cssClass) {
  795.         this.invalidHandleClasses.push(cssClass);
  796.     },
  797.     /**
  798.      * Unsets an excluded tag name set by addInvalidHandleType
  799.      * @method removeInvalidHandleType
  800.      * @param {string} tagName the type of element to unexclude
  801.      */
  802.     removeInvalidHandleType: function(tagName) {
  803.         var type = tagName.toUpperCase();
  804.         // this.invalidHandleTypes[type] = null;
  805.         delete this.invalidHandleTypes[type];
  806.     },
  807.     /**
  808.      * Unsets an invalid handle id
  809.      * @method removeInvalidHandleId
  810.      * @param {string} id the id of the element to re-enable
  811.      */
  812.     removeInvalidHandleId: function(id) {
  813.         if (typeof id !== "string") {
  814.             id = Ext.id(id);
  815.         }
  816.         delete this.invalidHandleIds[id];
  817.     },
  818.     /**
  819.      * Unsets an invalid css class
  820.      * @method removeInvalidHandleClass
  821.      * @param {string} cssClass the class of the element(s) you wish to
  822.      * re-enable
  823.      */
  824.     removeInvalidHandleClass: function(cssClass) {
  825.         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
  826.             if (this.invalidHandleClasses[i] == cssClass) {
  827.                 delete this.invalidHandleClasses[i];
  828.             }
  829.         }
  830.     },
  831.     /**
  832.      * Checks the tag exclusion list to see if this click should be ignored
  833.      * @method isValidHandleChild
  834.      * @param {HTMLElement} node the HTMLElement to evaluate
  835.      * @return {boolean} true if this is a valid tag type, false if not
  836.      */
  837.     isValidHandleChild: function(node) {
  838.         var valid = true;
  839.         // var n = (node.nodeName == "#text") ? node.parentNode : node;
  840.         var nodeName;
  841.         try {
  842.             nodeName = node.nodeName.toUpperCase();
  843.         } catch(e) {
  844.             nodeName = node.nodeName;
  845.         }
  846.         valid = valid && !this.invalidHandleTypes[nodeName];
  847.         valid = valid && !this.invalidHandleIds[node.id];
  848.         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
  849.             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
  850.         }
  851.         return valid;
  852.     },
  853.     /**
  854.      * Create the array of horizontal tick marks if an interval was specified
  855.      * in setXConstraint().
  856.      * @method setXTicks
  857.      * @private
  858.      */
  859.     setXTicks: function(iStartX, iTickSize) {
  860.         this.xTicks = [];
  861.         this.xTickSize = iTickSize;
  862.         var tickMap = {};
  863.         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
  864.             if (!tickMap[i]) {
  865.                 this.xTicks[this.xTicks.length] = i;
  866.                 tickMap[i] = true;
  867.             }
  868.         }
  869.         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
  870.             if (!tickMap[i]) {
  871.                 this.xTicks[this.xTicks.length] = i;
  872.                 tickMap[i] = true;
  873.             }
  874.         }
  875.         this.xTicks.sort(this.DDM.numericSort) ;
  876.     },
  877.     /**
  878.      * Create the array of vertical tick marks if an interval was specified in
  879.      * setYConstraint().
  880.      * @method setYTicks
  881.      * @private
  882.      */
  883.     setYTicks: function(iStartY, iTickSize) {
  884.         this.yTicks = [];
  885.         this.yTickSize = iTickSize;
  886.         var tickMap = {};
  887.         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
  888.             if (!tickMap[i]) {
  889.                 this.yTicks[this.yTicks.length] = i;
  890.                 tickMap[i] = true;
  891.             }
  892.         }
  893.         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
  894.             if (!tickMap[i]) {
  895.                 this.yTicks[this.yTicks.length] = i;
  896.                 tickMap[i] = true;
  897.             }
  898.         }
  899.         this.yTicks.sort(this.DDM.numericSort) ;
  900.     },
  901.     /**
  902.      * By default, the element can be dragged any place on the screen.  Use
  903.      * this method to limit the horizontal travel of the element.  Pass in
  904.      * 0,0 for the parameters if you want to lock the drag to the y axis.
  905.      * @method setXConstraint
  906.      * @param {int} iLeft the number of pixels the element can move to the left
  907.      * @param {int} iRight the number of pixels the element can move to the
  908.      * right
  909.      * @param {int} iTickSize optional parameter for specifying that the
  910.      * element
  911.      * should move iTickSize pixels at a time.
  912.      */
  913.     setXConstraint: function(iLeft, iRight, iTickSize) {
  914.         this.leftConstraint = iLeft;
  915.         this.rightConstraint = iRight;
  916.         this.minX = this.initPageX - iLeft;
  917.         this.maxX = this.initPageX + iRight;
  918.         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
  919.         this.constrainX = true;
  920.     },
  921.     /**
  922.      * Clears any constraints applied to this instance.  Also clears ticks
  923.      * since they can't exist independent of a constraint at this time.
  924.      * @method clearConstraints
  925.      */
  926.     clearConstraints: function() {
  927.         this.constrainX = false;
  928.         this.constrainY = false;
  929.         this.clearTicks();
  930.     },
  931.     /**
  932.      * Clears any tick interval defined for this instance
  933.      * @method clearTicks
  934.      */
  935.     clearTicks: function() {
  936.         this.xTicks = null;
  937.         this.yTicks = null;
  938.         this.xTickSize = 0;
  939.         this.yTickSize = 0;
  940.     },
  941.     /**
  942.      * By default, the element can be dragged any place on the screen.  Set
  943.      * this to limit the vertical travel of the element.  Pass in 0,0 for the
  944.      * parameters if you want to lock the drag to the x axis.
  945.      * @method setYConstraint
  946.      * @param {int} iUp the number of pixels the element can move up
  947.      * @param {int} iDown the number of pixels the element can move down
  948.      * @param {int} iTickSize optional parameter for specifying that the
  949.      * element should move iTickSize pixels at a time.
  950.      */
  951.     setYConstraint: function(iUp, iDown, iTickSize) {
  952.         this.topConstraint = iUp;
  953.         this.bottomConstraint = iDown;
  954.         this.minY = this.initPageY - iUp;
  955.         this.maxY = this.initPageY + iDown;
  956.         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
  957.         this.constrainY = true;
  958.     },
  959.     /**
  960.      * resetConstraints must be called if you manually reposition a dd element.
  961.      * @method resetConstraints
  962.      * @param {boolean} maintainOffset
  963.      */
  964.     resetConstraints: function() {
  965.         // Maintain offsets if necessary
  966.         if (this.initPageX || this.initPageX === 0) {
  967.             // figure out how much this thing has moved
  968.             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
  969.             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
  970.             this.setInitPosition(dx, dy);
  971.         // This is the first time we have detected the element's position
  972.         } else {
  973.             this.setInitPosition();
  974.         }
  975.         if (this.constrainX) {
  976.             this.setXConstraint( this.leftConstraint,
  977.                                  this.rightConstraint,
  978.                                  this.xTickSize        );
  979.         }
  980.         if (this.constrainY) {
  981.             this.setYConstraint( this.topConstraint,
  982.                                  this.bottomConstraint,
  983.                                  this.yTickSize         );
  984.         }
  985.     },
  986.     /**
  987.      * Normally the drag element is moved pixel by pixel, but we can specify
  988.      * that it move a number of pixels at a time.  This method resolves the
  989.      * location when we have it set up like this.
  990.      * @method getTick
  991.      * @param {int} val where we want to place the object
  992.      * @param {int[]} tickArray sorted array of valid points
  993.      * @return {int} the closest tick
  994.      * @private
  995.      */
  996.     getTick: function(val, tickArray) {
  997.         if (!tickArray) {
  998.             // If tick interval is not defined, it is effectively 1 pixel,
  999.             // so we return the value passed to us.
  1000.             return val;
  1001.         } else if (tickArray[0] >= val) {
  1002.             // The value is lower than the first tick, so we return the first
  1003.             // tick.
  1004.             return tickArray[0];
  1005.         } else {
  1006.             for (var i=0, len=tickArray.length; i<len; ++i) {
  1007.                 var next = i + 1;
  1008.                 if (tickArray[next] && tickArray[next] >= val) {
  1009.                     var diff1 = val - tickArray[i];
  1010.                     var diff2 = tickArray[next] - val;
  1011.                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
  1012.                 }
  1013.             }
  1014.             // The value is larger than the last tick, so we return the last
  1015.             // tick.
  1016.             return tickArray[tickArray.length - 1];
  1017.         }
  1018.     },
  1019.     /**
  1020.      * toString method
  1021.      * @method toString
  1022.      * @return {string} string representation of the dd obj
  1023.      */
  1024.     toString: function() {
  1025.         return ("DragDrop " + this.id);
  1026.     }
  1027. };
  1028. })();
  1029. /**
  1030.  * The drag and drop utility provides a framework for building drag and drop
  1031.  * applications.  In addition to enabling drag and drop for specific elements,
  1032.  * the drag and drop elements are tracked by the manager class, and the
  1033.  * interactions between the various elements are tracked during the drag and
  1034.  * the implementing code is notified about these important moments.
  1035.  */
  1036. // Only load the library once.  Rewriting the manager class would orphan
  1037. // existing drag and drop instances.
  1038. if (!Ext.dd.DragDropMgr) {
  1039. /**
  1040.  * @class Ext.dd.DragDropMgr
  1041.  * DragDropMgr is a singleton that tracks the element interaction for
  1042.  * all DragDrop items in the window.  Generally, you will not call
  1043.  * this class directly, but it does have helper methods that could
  1044.  * be useful in your DragDrop implementations.
  1045.  * @singleton
  1046.  */
  1047. Ext.dd.DragDropMgr = function() {
  1048.     var Event = Ext.EventManager;
  1049.     return {
  1050.         /**
  1051.          * Two dimensional Array of registered DragDrop objects.  The first
  1052.          * dimension is the DragDrop item group, the second the DragDrop
  1053.          * object.
  1054.          * @property ids
  1055.          * @type {string: string}
  1056.          * @private
  1057.          * @static
  1058.          */
  1059.         ids: {},
  1060.         /**
  1061.          * Array of element ids defined as drag handles.  Used to determine
  1062.          * if the element that generated the mousedown event is actually the
  1063.          * handle and not the html element itself.
  1064.          * @property handleIds
  1065.          * @type {string: string}
  1066.          * @private
  1067.          * @static
  1068.          */
  1069.         handleIds: {},
  1070.         /**
  1071.          * the DragDrop object that is currently being dragged
  1072.          * @property dragCurrent
  1073.          * @type DragDrop
  1074.          * @private
  1075.          * @static
  1076.          **/
  1077.         dragCurrent: null,
  1078.         /**
  1079.          * the DragDrop object(s) that are being hovered over
  1080.          * @property dragOvers
  1081.          * @type Array
  1082.          * @private
  1083.          * @static
  1084.          */
  1085.         dragOvers: {},
  1086.         /**
  1087.          * the X distance between the cursor and the object being dragged
  1088.          * @property deltaX
  1089.          * @type int
  1090.          * @private
  1091.          * @static
  1092.          */
  1093.         deltaX: 0,
  1094.         /**
  1095.          * the Y distance between the cursor and the object being dragged
  1096.          * @property deltaY
  1097.          * @type int
  1098.          * @private
  1099.          * @static
  1100.          */
  1101.         deltaY: 0,
  1102.         /**
  1103.          * Flag to determine if we should prevent the default behavior of the
  1104.          * events we define. By default this is true, but this can be set to
  1105.          * false if you need the default behavior (not recommended)
  1106.          * @property preventDefault
  1107.          * @type boolean
  1108.          * @static
  1109.          */
  1110.         preventDefault: true,
  1111.         /**
  1112.          * Flag to determine if we should stop the propagation of the events
  1113.          * we generate. This is true by default but you may want to set it to
  1114.          * false if the html element contains other features that require the
  1115.          * mouse click.
  1116.          * @property stopPropagation
  1117.          * @type boolean
  1118.          * @static
  1119.          */
  1120.         stopPropagation: true,
  1121.         /**
  1122.          * Internal flag that is set to true when drag and drop has been
  1123.          * intialized
  1124.          * @property initialized
  1125.          * @private
  1126.          * @static
  1127.          */
  1128.         initialized: false,
  1129.         /**
  1130.          * All drag and drop can be disabled.
  1131.          * @property locked
  1132.          * @private
  1133.          * @static
  1134.          */
  1135.         locked: false,
  1136.         /**
  1137.          * Called the first time an element is registered.
  1138.          * @method init
  1139.          * @private
  1140.          * @static
  1141.          */
  1142.         init: function() {
  1143.             this.initialized = true;
  1144.         },
  1145.         /**
  1146.          * In point mode, drag and drop interaction is defined by the
  1147.          * location of the cursor during the drag/drop
  1148.          * @property POINT
  1149.          * @type int
  1150.          * @static
  1151.          */
  1152.         POINT: 0,
  1153.         /**
  1154.          * In intersect mode, drag and drop interaction is defined by the
  1155.          * overlap of two or more drag and drop objects.
  1156.          * @property INTERSECT
  1157.          * @type int
  1158.          * @static
  1159.          */
  1160.         INTERSECT: 1,
  1161.         /**
  1162.          * The current drag and drop mode.  Default: POINT
  1163.          * @property mode
  1164.          * @type int
  1165.          * @static
  1166.          */
  1167.         mode: 0,
  1168.         /**
  1169.          * Runs method on all drag and drop objects
  1170.          * @method _execOnAll
  1171.          * @private
  1172.          * @static
  1173.          */
  1174.         _execOnAll: function(sMethod, args) {
  1175.             for (var i in this.ids) {
  1176.                 for (var j in this.ids[i]) {
  1177.                     var oDD = this.ids[i][j];
  1178.                     if (! this.isTypeOfDD(oDD)) {
  1179.                         continue;
  1180.                     }
  1181.                     oDD[sMethod].apply(oDD, args);
  1182.                 }
  1183.             }
  1184.         },
  1185.         /**
  1186.          * Drag and drop initialization.  Sets up the global event handlers
  1187.          * @method _onLoad
  1188.          * @private
  1189.          * @static
  1190.          */
  1191.         _onLoad: function() {
  1192.             this.init();
  1193.             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
  1194.             Event.on(document, "mousemove", this.handleMouseMove, this, true);
  1195.             Event.on(window,   "unload",    this._onUnload, this, true);
  1196.             Event.on(window,   "resize",    this._onResize, this, true);
  1197.             // Event.on(window,   "mouseout",    this._test);
  1198.         },
  1199.         /**
  1200.          * Reset constraints on all drag and drop objs
  1201.          * @method _onResize
  1202.          * @private
  1203.          * @static
  1204.          */
  1205.         _onResize: function(e) {
  1206.             this._execOnAll("resetConstraints", []);
  1207.         },
  1208.         /**
  1209.          * Lock all drag and drop functionality
  1210.          * @method lock
  1211.          * @static
  1212.          */
  1213.         lock: function() { this.locked = true; },
  1214.         /**
  1215.          * Unlock all drag and drop functionality
  1216.          * @method unlock
  1217.          * @static
  1218.          */
  1219.         unlock: function() { this.locked = false; },
  1220.         /**
  1221.          * Is drag and drop locked?
  1222.          * @method isLocked
  1223.          * @return {boolean} True if drag and drop is locked, false otherwise.
  1224.          * @static
  1225.          */
  1226.         isLocked: function() { return this.locked; },
  1227.         /**
  1228.          * Location cache that is set for all drag drop objects when a drag is
  1229.          * initiated, cleared when the drag is finished.
  1230.          * @property locationCache
  1231.          * @private
  1232.          * @static
  1233.          */
  1234.         locationCache: {},
  1235.         /**
  1236.          * Set useCache to false if you want to force object the lookup of each
  1237.          * drag and drop linked element constantly during a drag.
  1238.          * @property useCache
  1239.          * @type boolean
  1240.          * @static
  1241.          */
  1242.         useCache: true,
  1243.         /**
  1244.          * The number of pixels that the mouse needs to move after the
  1245.          * mousedown before the drag is initiated.  Default=3;
  1246.          * @property clickPixelThresh
  1247.          * @type int
  1248.          * @static
  1249.          */
  1250.         clickPixelThresh: 3,
  1251.         /**
  1252.          * The number of milliseconds after the mousedown event to initiate the
  1253.          * drag if we don't get a mouseup event. Default=1000
  1254.          * @property clickTimeThresh
  1255.          * @type int
  1256.          * @static
  1257.          */
  1258.         clickTimeThresh: 350,
  1259.         /**
  1260.          * Flag that indicates that either the drag pixel threshold or the
  1261.          * mousdown time threshold has been met
  1262.          * @property dragThreshMet
  1263.          * @type boolean
  1264.          * @private
  1265.          * @static
  1266.          */
  1267.         dragThreshMet: false,
  1268.         /**
  1269.          * Timeout used for the click time threshold
  1270.          * @property clickTimeout
  1271.          * @type Object
  1272.          * @private
  1273.          * @static
  1274.          */
  1275.         clickTimeout: null,
  1276.         /**
  1277.          * The X position of the mousedown event stored for later use when a
  1278.          * drag threshold is met.
  1279.          * @property startX
  1280.          * @type int
  1281.          * @private
  1282.          * @static
  1283.          */
  1284.         startX: 0,
  1285.         /**
  1286.          * The Y position of the mousedown event stored for later use when a
  1287.          * drag threshold is met.
  1288.          * @property startY
  1289.          * @type int
  1290.          * @private
  1291.          * @static
  1292.          */
  1293.         startY: 0,
  1294.         /**
  1295.          * Each DragDrop instance must be registered with the DragDropMgr.
  1296.          * This is executed in DragDrop.init()
  1297.          * @method regDragDrop
  1298.          * @param {DragDrop} oDD the DragDrop object to register
  1299.          * @param {String} sGroup the name of the group this element belongs to
  1300.          * @static
  1301.          */
  1302.         regDragDrop: function(oDD, sGroup) {
  1303.             if (!this.initialized) { this.init(); }
  1304.             if (!this.ids[sGroup]) {
  1305.                 this.ids[sGroup] = {};
  1306.             }
  1307.             this.ids[sGroup][oDD.id] = oDD;
  1308.         },
  1309.         /**
  1310.          * Removes the supplied dd instance from the supplied group. Executed
  1311.          * by DragDrop.removeFromGroup, so don't call this function directly.
  1312.          * @method removeDDFromGroup
  1313.          * @private
  1314.          * @static
  1315.          */
  1316.         removeDDFromGroup: function(oDD, sGroup) {
  1317.             if (!this.ids[sGroup]) {
  1318.                 this.ids[sGroup] = {};
  1319.             }
  1320.             var obj = this.ids[sGroup];
  1321.             if (obj && obj[oDD.id]) {
  1322.                 delete obj[oDD.id];
  1323.             }
  1324.         },
  1325.         /**
  1326.          * Unregisters a drag and drop item.  This is executed in
  1327.          * DragDrop.unreg, use that method instead of calling this directly.
  1328.          * @method _remove
  1329.          * @private
  1330.          * @static
  1331.          */
  1332.         _remove: function(oDD) {
  1333.             for (var g in oDD.groups) {
  1334.                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
  1335.                     delete this.ids[g][oDD.id];
  1336.                 }
  1337.             }
  1338.             delete this.handleIds[oDD.id];
  1339.         },
  1340.         /**
  1341.          * Each DragDrop handle element must be registered.  This is done
  1342.          * automatically when executing DragDrop.setHandleElId()
  1343.          * @method regHandle
  1344.          * @param {String} sDDId the DragDrop id this element is a handle for
  1345.          * @param {String} sHandleId the id of the element that is the drag
  1346.          * handle
  1347.          * @static
  1348.          */
  1349.         regHandle: function(sDDId, sHandleId) {
  1350.             if (!this.handleIds[sDDId]) {
  1351.                 this.handleIds[sDDId] = {};
  1352.             }
  1353.             this.handleIds[sDDId][sHandleId] = sHandleId;
  1354.         },
  1355.         /**
  1356.          * Utility function to determine if a given element has been
  1357.          * registered as a drag drop item.
  1358.          * @method isDragDrop
  1359.          * @param {String} id the element id to check
  1360.          * @return {boolean} true if this element is a DragDrop item,
  1361.          * false otherwise
  1362.          * @static
  1363.          */
  1364.         isDragDrop: function(id) {
  1365.             return ( this.getDDById(id) ) ? true : false;
  1366.         },
  1367.         /**
  1368.          * Returns the drag and drop instances that are in all groups the
  1369.          * passed in instance belongs to.
  1370.          * @method getRelated
  1371.          * @param {DragDrop} p_oDD the obj to get related data for
  1372.          * @param {boolean} bTargetsOnly if true, only return targetable objs
  1373.          * @return {DragDrop[]} the related instances
  1374.          * @static
  1375.          */
  1376.         getRelated: function(p_oDD, bTargetsOnly) {
  1377.             var oDDs = [];
  1378.             for (var i in p_oDD.groups) {
  1379.                 for (var j in this.ids[i]) {
  1380.                     var dd = this.ids[i][j];
  1381.                     if (! this.isTypeOfDD(dd)) {
  1382.                         continue;
  1383.                     }
  1384.                     if (!bTargetsOnly || dd.isTarget) {
  1385.                         oDDs[oDDs.length] = dd;
  1386.                     }
  1387.                 }
  1388.             }
  1389.             return oDDs;
  1390.         },
  1391.         /**
  1392.          * Returns true if the specified dd target is a legal target for
  1393.          * the specifice drag obj
  1394.          * @method isLegalTarget
  1395.          * @param {DragDrop} the drag obj
  1396.          * @param {DragDrop} the target
  1397.          * @return {boolean} true if the target is a legal target for the
  1398.          * dd obj
  1399.          * @static
  1400.          */
  1401.         isLegalTarget: function (oDD, oTargetDD) {
  1402.             var targets = this.getRelated(oDD, true);
  1403.             for (var i=0, len=targets.length;i<len;++i) {
  1404.                 if (targets[i].id == oTargetDD.id) {
  1405.                     return true;
  1406.                 }
  1407.             }
  1408.             return false;
  1409.         },
  1410.         /**
  1411.          * My goal is to be able to transparently determine if an object is
  1412.          * typeof DragDrop, and the exact subclass of DragDrop.  typeof
  1413.          * returns "object", oDD.constructor.toString() always returns
  1414.          * "DragDrop" and not the name of the subclass.  So for now it just
  1415.          * evaluates a well-known variable in DragDrop.
  1416.          * @method isTypeOfDD
  1417.          * @param {Object} the object to evaluate
  1418.          * @return {boolean} true if typeof oDD = DragDrop
  1419.          * @static
  1420.          */
  1421.         isTypeOfDD: function (oDD) {
  1422.             return (oDD && oDD.__ygDragDrop);
  1423.         },
  1424.         /**
  1425.          * Utility function to determine if a given element has been
  1426.          * registered as a drag drop handle for the given Drag Drop object.
  1427.          * @method isHandle
  1428.          * @param {String} id the element id to check
  1429.          * @return {boolean} true if this element is a DragDrop handle, false
  1430.          * otherwise
  1431.          * @static
  1432.          */
  1433.         isHandle: function(sDDId, sHandleId) {
  1434.             return ( this.handleIds[sDDId] &&
  1435.                             this.handleIds[sDDId][sHandleId] );
  1436.         },
  1437.         /**
  1438.          * Returns the DragDrop instance for a given id
  1439.          * @method getDDById
  1440.          * @param {String} id the id of the DragDrop object
  1441.          * @return {DragDrop} the drag drop object, null if it is not found
  1442.          * @static
  1443.          */
  1444.         getDDById: function(id) {
  1445.             for (var i in this.ids) {
  1446.                 if (this.ids[i][id]) {
  1447.                     return this.ids[i][id];
  1448.                 }
  1449.             }
  1450.             return null;
  1451.         },
  1452.         /**
  1453.          * Fired after a registered DragDrop object gets the mousedown event.
  1454.          * Sets up the events required to track the object being dragged
  1455.          * @method handleMouseDown
  1456.          * @param {Event} e the event
  1457.          * @param oDD the DragDrop object being dragged
  1458.          * @private
  1459.          * @static
  1460.          */
  1461.         handleMouseDown: function(e, oDD) {
  1462.             if(Ext.QuickTips){
  1463.                 Ext.QuickTips.disable();
  1464.             }
  1465.             if(this.dragCurrent){
  1466.                 // the original browser mouseup wasn't handled (e.g. outside FF browser window)
  1467.                 // so clean up first to avoid breaking the next drag
  1468.                 this.handleMouseUp(e);
  1469.             }
  1470.             
  1471.             this.currentTarget = e.getTarget();
  1472.             this.dragCurrent = oDD;
  1473.             var el = oDD.getEl();
  1474.             // track start position
  1475.             this.startX = e.getPageX();
  1476.             this.startY = e.getPageY();
  1477.             this.deltaX = this.startX - el.offsetLeft;
  1478.             this.deltaY = this.startY - el.offsetTop;
  1479.             this.dragThreshMet = false;
  1480.             this.clickTimeout = setTimeout(
  1481.                     function() {
  1482.                         var DDM = Ext.dd.DDM;
  1483.                         DDM.startDrag(DDM.startX, DDM.startY);
  1484.                     },
  1485.                     this.clickTimeThresh );
  1486.         },
  1487.         /**
  1488.          * Fired when either the drag pixel threshol or the mousedown hold
  1489.          * time threshold has been met.
  1490.          * @method startDrag
  1491.          * @param x {int} the X position of the original mousedown
  1492.          * @param y {int} the Y position of the original mousedown
  1493.          * @static
  1494.          */
  1495.         startDrag: function(x, y) {
  1496.             clearTimeout(this.clickTimeout);
  1497.             if (this.dragCurrent) {
  1498.                 this.dragCurrent.b4StartDrag(x, y);
  1499.                 this.dragCurrent.startDrag(x, y);
  1500.             }
  1501.             this.dragThreshMet = true;
  1502.         },
  1503.         /**
  1504.          * Internal function to handle the mouseup event.  Will be invoked
  1505.          * from the context of the document.
  1506.          * @method handleMouseUp
  1507.          * @param {Event} e the event
  1508.          * @private
  1509.          * @static
  1510.          */
  1511.         handleMouseUp: function(e) {
  1512.             if(Ext.QuickTips){
  1513.                 Ext.QuickTips.enable();
  1514.             }
  1515.             if (! this.dragCurrent) {
  1516.                 return;
  1517.             }
  1518.             clearTimeout(this.clickTimeout);
  1519.             if (this.dragThreshMet) {
  1520.                 this.fireEvents(e, true);
  1521.             } else {
  1522.             }
  1523.             this.stopDrag(e);
  1524.             this.stopEvent(e);
  1525.         },
  1526.         /**
  1527.          * Utility to stop event propagation and event default, if these
  1528.          * features are turned on.
  1529.          * @method stopEvent
  1530.          * @param {Event} e the event as returned by this.getEvent()
  1531.          * @static
  1532.          */
  1533.         stopEvent: function(e){
  1534.             if(this.stopPropagation) {
  1535.                 e.stopPropagation();
  1536.             }
  1537.             if (this.preventDefault) {
  1538.                 e.preventDefault();
  1539.             }
  1540.         },
  1541.         /**
  1542.          * Internal function to clean up event handlers after the drag
  1543.          * operation is complete
  1544.          * @method stopDrag
  1545.          * @param {Event} e the event
  1546.          * @private
  1547.          * @static
  1548.          */
  1549.         stopDrag: function(e) {
  1550.             // Fire the drag end event for the item that was dragged
  1551.             if (this.dragCurrent) {
  1552.                 if (this.dragThreshMet) {
  1553.                     this.dragCurrent.b4EndDrag(e);
  1554.                     this.dragCurrent.endDrag(e);
  1555.                 }
  1556.                 this.dragCurrent.onMouseUp(e);
  1557.             }
  1558.             this.dragCurrent = null;
  1559.             this.dragOvers = {};
  1560.         },
  1561.         /**
  1562.          * Internal function to handle the mousemove event.  Will be invoked
  1563.          * from the context of the html element.
  1564.          *
  1565.          * @TODO figure out what we can do about mouse events lost when the
  1566.          * user drags objects beyond the window boundary.  Currently we can
  1567.          * detect this in internet explorer by verifying that the mouse is
  1568.          * down during the mousemove event.  Firefox doesn't give us the
  1569.          * button state on the mousemove event.
  1570.          * @method handleMouseMove
  1571.          * @param {Event} e the event
  1572.          * @private
  1573.          * @static
  1574.          */
  1575.         handleMouseMove: function(e) {
  1576.             if (! this.dragCurrent) {
  1577.                 return true;
  1578.             }
  1579.             // var button = e.which || e.button;
  1580.             // check for IE mouseup outside of page boundary
  1581.             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
  1582.                 this.stopEvent(e);
  1583.                 return this.handleMouseUp(e);
  1584.             }
  1585.             if (!this.dragThreshMet) {
  1586.                 var diffX = Math.abs(this.startX - e.getPageX());
  1587.                 var diffY = Math.abs(this.startY - e.getPageY());
  1588.                 if (diffX > this.clickPixelThresh ||
  1589.                             diffY > this.clickPixelThresh) {
  1590.                     this.startDrag(this.startX, this.startY);
  1591.                 }
  1592.             }
  1593.             if (this.dragThreshMet) {
  1594.                 this.dragCurrent.b4Drag(e);
  1595.                 this.dragCurrent.onDrag(e);
  1596.                 if(!this.dragCurrent.moveOnly){
  1597.                     this.fireEvents(e, false);
  1598.                 }
  1599.             }
  1600.             this.stopEvent(e);
  1601.             return true;
  1602.         },
  1603.         /**
  1604.          * Iterates over all of the DragDrop elements to find ones we are
  1605.          * hovering over or dropping on
  1606.          * @method fireEvents
  1607.          * @param {Event} e the event
  1608.          * @param {boolean} isDrop is this a drop op or a mouseover op?
  1609.          * @private
  1610.          * @static
  1611.          */
  1612.         fireEvents: function(e, isDrop) {
  1613.             var dc = this.dragCurrent;
  1614.             // If the user did the mouse up outside of the window, we could
  1615.             // get here even though we have ended the drag.
  1616.             if (!dc || dc.isLocked()) {
  1617.                 return;
  1618.             }
  1619.             var pt = e.getPoint();
  1620.             // cache the previous dragOver array
  1621.             var oldOvers = [];
  1622.             var outEvts   = [];
  1623.             var overEvts  = [];
  1624.             var dropEvts  = [];
  1625.             var enterEvts = [];
  1626.             // Check to see if the object(s) we were hovering over is no longer
  1627.             // being hovered over so we can fire the onDragOut event
  1628.             for (var i in this.dragOvers) {
  1629.                 var ddo = this.dragOvers[i];
  1630.                 if (! this.isTypeOfDD(ddo)) {
  1631.                     continue;
  1632.                 }
  1633.                 if (! this.isOverTarget(pt, ddo, this.mode)) {
  1634.                     outEvts.push( ddo );
  1635.                 }
  1636.                 oldOvers[i] = true;
  1637.                 delete this.dragOvers[i];
  1638.             }
  1639.             for (var sGroup in dc.groups) {
  1640.                 if ("string" != typeof sGroup) {
  1641.                     continue;
  1642.                 }
  1643.                 for (i in this.ids[sGroup]) {
  1644.                     var oDD = this.ids[sGroup][i];
  1645.                     if (! this.isTypeOfDD(oDD)) {
  1646.                         continue;
  1647.                     }
  1648.                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
  1649.                         if (this.isOverTarget(pt, oDD, this.mode)) {
  1650.                             // look for drop interactions
  1651.                             if (isDrop) {
  1652.                                 dropEvts.push( oDD );
  1653.                             // look for drag enter and drag over interactions
  1654.                             } else {
  1655.                                 // initial drag over: dragEnter fires
  1656.                                 if (!oldOvers[oDD.id]) {
  1657.                                     enterEvts.push( oDD );
  1658.                                 // subsequent drag overs: dragOver fires
  1659.                                 } else {
  1660.                                     overEvts.push( oDD );
  1661.                                 }
  1662.                                 this.dragOvers[oDD.id] = oDD;
  1663.                             }
  1664.                         }
  1665.                     }
  1666.                 }
  1667.             }
  1668.             if (this.mode) {
  1669.                 if (outEvts.length) {
  1670.                     dc.b4DragOut(e, outEvts);
  1671.                     dc.onDragOut(e, outEvts);
  1672.                 }
  1673.                 if (enterEvts.length) {
  1674.                     dc.onDragEnter(e, enterEvts);
  1675.                 }
  1676.                 if (overEvts.length) {
  1677.                     dc.b4DragOver(e, overEvts);
  1678.                     dc.onDragOver(e, overEvts);
  1679.                 }
  1680.                 if (dropEvts.length) {
  1681.                     dc.b4DragDrop(e, dropEvts);
  1682.                     dc.onDragDrop(e, dropEvts);
  1683.                 }
  1684.             } else {
  1685.                 // fire dragout events
  1686.                 var len = 0;
  1687.                 for (i=0, len=outEvts.length; i<len; ++i) {
  1688.                     dc.b4DragOut(e, outEvts[i].id);
  1689.                     dc.onDragOut(e, outEvts[i].id);
  1690.                 }
  1691.                 // fire enter events
  1692.                 for (i=0,len=enterEvts.length; i<len; ++i) {
  1693.                     // dc.b4DragEnter(e, oDD.id);
  1694.                     dc.onDragEnter(e, enterEvts[i].id);
  1695.                 }
  1696.                 // fire over events
  1697.                 for (i=0,len=overEvts.length; i<len; ++i) {
  1698.                     dc.b4DragOver(e, overEvts[i].id);
  1699.                     dc.onDragOver(e, overEvts[i].id);
  1700.                 }
  1701.                 // fire drop events
  1702.                 for (i=0, len=dropEvts.length; i<len; ++i) {
  1703.                     dc.b4DragDrop(e, dropEvts[i].id);
  1704.                     dc.onDragDrop(e, dropEvts[i].id);
  1705.                 }
  1706.             }
  1707.             // notify about a drop that did not find a target
  1708.             if (isDrop && !dropEvts.length) {
  1709.                 dc.onInvalidDrop(e);
  1710.             }
  1711.         },
  1712.         /**
  1713.          * Helper function for getting the best match from the list of drag
  1714.          * and drop objects returned by the drag and drop events when we are
  1715.          * in INTERSECT mode.  It returns either the first object that the
  1716.          * cursor is over, or the object that has the greatest overlap with
  1717.          * the dragged element.
  1718.          * @method getBestMatch
  1719.          * @param  {DragDrop[]} dds The array of drag and drop objects
  1720.          * targeted
  1721.          * @return {DragDrop}       The best single match
  1722.          * @static
  1723.          */
  1724.         getBestMatch: function(dds) {
  1725.             var winner = null;
  1726.             // Return null if the input is not what we expect
  1727.             //if (!dds || !dds.length || dds.length == 0) {
  1728.                // winner = null;
  1729.             // If there is only one item, it wins
  1730.             //} else if (dds.length == 1) {
  1731.             var len = dds.length;
  1732.             if (len == 1) {
  1733.                 winner = dds[0];
  1734.             } else {
  1735.                 // Loop through the targeted items
  1736.                 for (var i=0; i<len; ++i) {
  1737.                     var dd = dds[i];
  1738.                     // If the cursor is over the object, it wins.  If the
  1739.                     // cursor is over multiple matches, the first one we come
  1740.                     // to wins.
  1741.                     if (dd.cursorIsOver) {
  1742.                         winner = dd;
  1743.                         break;
  1744.                     // Otherwise the object with the most overlap wins
  1745.                     } else {
  1746.                         if (!winner ||
  1747.                             winner.overlap.getArea() < dd.overlap.getArea()) {
  1748.                             winner = dd;
  1749.                         }
  1750.                     }
  1751.                 }
  1752.             }
  1753.             return winner;
  1754.         },
  1755.         /**
  1756.          * Refreshes the cache of the top-left and bottom-right points of the
  1757.          * drag and drop objects in the specified group(s).  This is in the
  1758.          * format that is stored in the drag and drop instance, so typical
  1759.          * usage is:
  1760.          * <code>
  1761.          * Ext.dd.DragDropMgr.refreshCache(ddinstance.groups);
  1762.          * </code>
  1763.          * Alternatively:
  1764.          * <code>
  1765.          * Ext.dd.DragDropMgr.refreshCache({group1:true, group2:true});
  1766.          * </code>
  1767.          * @TODO this really should be an indexed array.  Alternatively this
  1768.          * method could accept both.
  1769.          * @method refreshCache
  1770.          * @param {Object} groups an associative array of groups to refresh
  1771.          * @static
  1772.          */
  1773.         refreshCache: function(groups) {
  1774.             for (var sGroup in groups) {
  1775.                 if ("string" != typeof sGroup) {
  1776.                     continue;
  1777.                 }
  1778.                 for (var i in this.ids[sGroup]) {
  1779.                     var oDD = this.ids[sGroup][i];
  1780.                     if (this.isTypeOfDD(oDD)) {
  1781.                     // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
  1782.                         var loc = this.getLocation(oDD);
  1783.                         if (loc) {
  1784.                             this.locationCache[oDD.id] = loc;
  1785.                         } else {
  1786.                             delete this.locationCache[oDD.id];
  1787.                             // this will unregister the drag and drop object if
  1788.                             // the element is not in a usable state
  1789.                             // oDD.unreg();
  1790.                         }
  1791.                     }
  1792.                 }
  1793.             }
  1794.         },
  1795.         /**
  1796.          * This checks to make sure an element exists and is in the DOM.  The
  1797.          * main purpose is to handle cases where innerHTML is used to remove
  1798.          * drag and drop objects from the DOM.  IE provides an 'unspecified
  1799.          * error' when trying to access the offsetParent of such an element
  1800.          * @method verifyEl
  1801.          * @param {HTMLElement} el the element to check
  1802.          * @return {boolean} true if the element looks usable
  1803.          * @static
  1804.          */
  1805.         verifyEl: function(el) {
  1806.             if (el) {
  1807.                 var parent;
  1808.                 if(Ext.isIE){
  1809.                     try{
  1810.                         parent = el.offsetParent;
  1811.                     }catch(e){}
  1812.                 }else{
  1813.                     parent = el.offsetParent;
  1814.                 }
  1815.                 if (parent) {
  1816.                     return true;
  1817.                 }
  1818.             }
  1819.             return false;
  1820.         },
  1821.         /**
  1822.          * Returns a Region object containing the drag and drop element's position
  1823.          * and size, including the padding configured for it
  1824.          * @method getLocation
  1825.          * @param {DragDrop} oDD the drag and drop object to get the
  1826.          *                       location for
  1827.          * @return {Ext.lib.Region} a Region object representing the total area
  1828.          *                             the element occupies, including any padding
  1829.          *                             the instance is configured for.
  1830.          * @static
  1831.          */
  1832.         getLocation: function(oDD) {
  1833.             if (! this.isTypeOfDD(oDD)) {
  1834.                 return null;
  1835.             }
  1836.             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
  1837.             try {
  1838.                 pos= Ext.lib.Dom.getXY(el);
  1839.             } catch (e) { }
  1840.             if (!pos) {
  1841.                 return null;
  1842.             }
  1843.             x1 = pos[0];
  1844.             x2 = x1 + el.offsetWidth;
  1845.             y1 = pos[1];
  1846.             y2 = y1 + el.offsetHeight;
  1847.             t = y1 - oDD.padding[0];
  1848.             r = x2 + oDD.padding[1];
  1849.             b = y2 + oDD.padding[2];
  1850.             l = x1 - oDD.padding[3];
  1851.             return new Ext.lib.Region( t, r, b, l );
  1852.         },
  1853.         /**
  1854.          * Checks the cursor location to see if it over the target
  1855.          * @method isOverTarget
  1856.          * @param {Ext.lib.Point} pt The point to evaluate
  1857.          * @param {DragDrop} oTarget the DragDrop object we are inspecting
  1858.          * @return {boolean} true if the mouse is over the target
  1859.          * @private
  1860.          * @static
  1861.          */
  1862.         isOverTarget: function(pt, oTarget, intersect) {
  1863.             // use cache if available
  1864.             var loc = this.locationCache[oTarget.id];
  1865.             if (!loc || !this.useCache) {
  1866.                 loc = this.getLocation(oTarget);
  1867.                 this.locationCache[oTarget.id] = loc;
  1868.             }
  1869.             if (!loc) {
  1870.                 return false;
  1871.             }
  1872.             oTarget.cursorIsOver = loc.contains( pt );
  1873.             // DragDrop is using this as a sanity check for the initial mousedown
  1874.             // in this case we are done.  In POINT mode, if the drag obj has no
  1875.             // contraints, we are also done. Otherwise we need to evaluate the
  1876.             // location of the target as related to the actual location of the
  1877.             // dragged element.
  1878.             var dc = this.dragCurrent;
  1879.             if (!dc || !dc.getTargetCoord ||
  1880.                     (!intersect && !dc.constrainX && !dc.constrainY)) {
  1881.                 return oTarget.cursorIsOver;
  1882.             }
  1883.             oTarget.overlap = null;
  1884.             // Get the current location of the drag element, this is the
  1885.             // location of the mouse event less the delta that represents
  1886.             // where the original mousedown happened on the element.  We
  1887.             // need to consider constraints and ticks as well.
  1888.             var pos = dc.getTargetCoord(pt.x, pt.y);
  1889.             var el = dc.getDragEl();
  1890.             var curRegion = new Ext.lib.Region( pos.y,
  1891.                                                    pos.x + el.offsetWidth,
  1892.                                                    pos.y + el.offsetHeight,
  1893.                                                    pos.x );
  1894.             var overlap = curRegion.intersect(loc);
  1895.             if (overlap) {
  1896.                 oTarget.overlap = overlap;
  1897.                 return (intersect) ? true : oTarget.cursorIsOver;
  1898.             } else {
  1899.                 return false;
  1900.             }
  1901.         },
  1902.         /**
  1903.          * unload event handler
  1904.          * @method _onUnload
  1905.          * @private
  1906.          * @static
  1907.          */
  1908.         _onUnload: function(e, me) {
  1909.             Ext.dd.DragDropMgr.unregAll();
  1910.         },
  1911.         /**
  1912.          * Cleans up the drag and drop events and objects.
  1913.          * @method unregAll
  1914.          * @private
  1915.          * @static
  1916.          */
  1917.         unregAll: function() {
  1918.             if (this.dragCurrent) {
  1919.                 this.stopDrag();
  1920.                 this.dragCurrent = null;
  1921.             }
  1922.             this._execOnAll("unreg", []);
  1923.             for (var i in this.elementCache) {
  1924.                 delete this.elementCache[i];
  1925.             }
  1926.             this.elementCache = {};
  1927.             this.ids = {};
  1928.         },
  1929.         /**
  1930.          * A cache of DOM elements
  1931.          * @property elementCache
  1932.          * @private
  1933.          * @static
  1934.          */
  1935.         elementCache: {},
  1936.         /**
  1937.          * Get the wrapper for the DOM element specified
  1938.          * @method getElWrapper
  1939.          * @param {String} id the id of the element to get
  1940.          * @return {Ext.dd.DDM.ElementWrapper} the wrapped element
  1941.          * @private
  1942.          * @deprecated This wrapper isn't that useful
  1943.          * @static
  1944.          */
  1945.         getElWrapper: function(id) {
  1946.             var oWrapper = this.elementCache[id];
  1947.             if (!oWrapper || !oWrapper.el) {
  1948.                 oWrapper = this.elementCache[id] =
  1949.                     new this.ElementWrapper(Ext.getDom(id));
  1950.             }
  1951.             return oWrapper;
  1952.         },
  1953.         /**
  1954.          * Returns the actual DOM element
  1955.          * @method getElement
  1956.          * @param {String} id the id of the elment to get
  1957.          * @return {Object} The element
  1958.          * @deprecated use Ext.lib.Ext.getDom instead
  1959.          * @static
  1960.          */
  1961.         getElement: function(id) {
  1962.             return Ext.getDom(id);
  1963.         },
  1964.         /**
  1965.          * Returns the style property for the DOM element (i.e.,
  1966.          * document.getElById(id).style)
  1967.          * @method getCss
  1968.          * @param {String} id the id of the elment to get
  1969.          * @return {Object} The style property of the element
  1970.          * @deprecated use Ext.lib.Dom instead
  1971.          * @static
  1972.          */
  1973.         getCss: function(id) {
  1974.             var el = Ext.getDom(id);
  1975.             return (el) ? el.style : null;
  1976.         },
  1977.         /**
  1978.          * Inner class for cached elements
  1979.          * @class DragDropMgr.ElementWrapper
  1980.          * @for DragDropMgr
  1981.          * @private
  1982.          * @deprecated
  1983.          */
  1984.         ElementWrapper: function(el) {
  1985.                 /**
  1986.                  * The element
  1987.                  * @property el
  1988.                  */
  1989.                 this.el = el || null;
  1990.                 /**
  1991.                  * The element id
  1992.                  * @property id
  1993.                  */
  1994.                 this.id = this.el && el.id;
  1995.                 /**
  1996.                  * A reference to the style property
  1997.                  * @property css
  1998.                  */
  1999.                 this.css = this.el && el.style;
  2000.             },
  2001.         /**
  2002.          * Returns the X position of an html element
  2003.          * @method getPosX
  2004.          * @param el the element for which to get the position
  2005.          * @return {int} the X coordinate
  2006.          * @for DragDropMgr
  2007.          * @deprecated use Ext.lib.Dom.getX instead
  2008.          * @static
  2009.          */
  2010.         getPosX: function(el) {
  2011.             return Ext.lib.Dom.getX(el);
  2012.         },
  2013.         /**
  2014.          * Returns the Y position of an html element
  2015.          * @method getPosY
  2016.          * @param el the element for which to get the position
  2017.          * @return {int} the Y coordinate
  2018.          * @deprecated use Ext.lib.Dom.getY instead
  2019.          * @static
  2020.          */
  2021.         getPosY: function(el) {
  2022.             return Ext.lib.Dom.getY(el);
  2023.         },
  2024.         /**
  2025.          * Swap two nodes.  In IE, we use the native method, for others we
  2026.          * emulate the IE behavior
  2027.          * @method swapNode
  2028.          * @param n1 the first node to swap
  2029.          * @param n2 the other node to swap
  2030.          * @static
  2031.          */
  2032.         swapNode: function(n1, n2) {
  2033.             if (n1.swapNode) {
  2034.                 n1.swapNode(n2);
  2035.             } else {
  2036.                 var p = n2.parentNode;
  2037.                 var s = n2.nextSibling;
  2038.                 if (s == n1) {
  2039.                     p.insertBefore(n1, n2);
  2040.                 } else if (n2 == n1.nextSibling) {
  2041.                     p.insertBefore(n2, n1);
  2042.                 } else {
  2043.                     n1.parentNode.replaceChild(n2, n1);
  2044.                     p.insertBefore(n1, s);
  2045.                 }
  2046.             }
  2047.         },
  2048.         /**
  2049.          * Returns the current scroll position
  2050.          * @method getScroll
  2051.          * @private
  2052.          * @static
  2053.          */
  2054.         getScroll: function () {
  2055.             var t, l, dde=document.documentElement, db=document.body;
  2056.             if (dde && (dde.scrollTop || dde.scrollLeft)) {
  2057.                 t = dde.scrollTop;
  2058.                 l = dde.scrollLeft;
  2059.             } else if (db) {
  2060.                 t = db.scrollTop;
  2061.                 l = db.scrollLeft;
  2062.             } else {
  2063.             }
  2064.             return { top: t, left: l };
  2065.         },
  2066.         /**
  2067.          * Returns the specified element style property
  2068.          * @method getStyle
  2069.          * @param {HTMLElement} el          the element
  2070.          * @param {string}      styleProp   the style property
  2071.          * @return {string} The value of the style property
  2072.          * @deprecated use Ext.lib.Dom.getStyle
  2073.          * @static
  2074.          */
  2075.         getStyle: function(el, styleProp) {
  2076.             return Ext.fly(el).getStyle(styleProp);
  2077.         },
  2078.         /**
  2079.          * Gets the scrollTop
  2080.          * @method getScrollTop
  2081.          * @return {int} the document's scrollTop
  2082.          * @static
  2083.          */
  2084.         getScrollTop: function () { return this.getScroll().top; },
  2085.         /**
  2086.          * Gets the scrollLeft
  2087.          * @method getScrollLeft
  2088.          * @return {int} the document's scrollTop
  2089.          * @static
  2090.          */
  2091.         getScrollLeft: function () { return this.getScroll().left; },
  2092.         /**
  2093.          * Sets the x/y position of an element to the location of the
  2094.          * target element.
  2095.          * @method moveToEl
  2096.          * @param {HTMLElement} moveEl      The element to move
  2097.          * @param {HTMLElement} targetEl    The position reference element
  2098.          * @static
  2099.          */
  2100.         moveToEl: function (moveEl, targetEl) {
  2101.             var aCoord = Ext.lib.Dom.getXY(targetEl);
  2102.             Ext.lib.Dom.setXY(moveEl, aCoord);
  2103.         },
  2104.         /**
  2105.          * Numeric array sort function
  2106.          * @method numericSort
  2107.          * @static
  2108.          */
  2109.         numericSort: function(a, b) { return (a - b); },
  2110.         /**
  2111.          * Internal counter
  2112.          * @property _timeoutCount
  2113.          * @private
  2114.          * @static
  2115.          */
  2116.         _timeoutCount: 0,
  2117.         /**
  2118.          * Trying to make the load order less important.  Without this we get
  2119.          * an error if this file is loaded before the Event Utility.
  2120.          * @method _addListeners
  2121.          * @private
  2122.          * @static
  2123.          */
  2124.         _addListeners: function() {
  2125.             var DDM = Ext.dd.DDM;
  2126.             if ( Ext.lib.Event && document ) {
  2127.                 DDM._onLoad();
  2128.             } else {
  2129.                 if (DDM._timeoutCount > 2000) {
  2130.                 } else {
  2131.                     setTimeout(DDM._addListeners, 10);
  2132.                     if (document && document.body) {
  2133.                         DDM._timeoutCount += 1;
  2134.                     }
  2135.                 }
  2136.             }
  2137.         },
  2138.         /**
  2139.          * Recursively searches the immediate parent and all child nodes for
  2140.          * the handle element in order to determine wheter or not it was
  2141.          * clicked.
  2142.          * @method handleWasClicked
  2143.          * @param node the html element to inspect
  2144.          * @static
  2145.          */
  2146.         handleWasClicked: function(node, id) {
  2147.             if (this.isHandle(id, node.id)) {
  2148.                 return true;
  2149.             } else {
  2150.                 // check to see if this is a text node child of the one we want
  2151.                 var p = node.parentNode;
  2152.                 while (p) {
  2153.                     if (this.isHandle(id, p.id)) {
  2154.                         return true;
  2155.                     } else {
  2156.                         p = p.parentNode;
  2157.                     }
  2158.                 }
  2159.             }
  2160.             return false;
  2161.         }
  2162.     };
  2163. }();
  2164. // shorter alias, save a few bytes
  2165. Ext.dd.DDM = Ext.dd.DragDropMgr;
  2166. Ext.dd.DDM._addListeners();
  2167. }
  2168. /**
  2169.  * @class Ext.dd.DD
  2170.  * A DragDrop implementation where the linked element follows the
  2171.  * mouse cursor during a drag.
  2172.  * @extends Ext.dd.DragDrop
  2173.  * @constructor
  2174.  * @param {String} id the id of the linked element
  2175.  * @param {String} sGroup the group of related DragDrop items
  2176.  * @param {object} config an object containing configurable attributes
  2177.  *                Valid properties for DD:
  2178.  *                    scroll
  2179.  */
  2180. Ext.dd.DD = function(id, sGroup, config) {
  2181.     if (id) {
  2182.         this.init(id, sGroup, config);
  2183.     }
  2184. };
  2185. Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
  2186.     /**
  2187.      * When set to true, the utility automatically tries to scroll the browser
  2188.      * window when a drag and drop element is dragged near the viewport boundary.
  2189.      * Defaults to true.
  2190.      * @property scroll
  2191.      * @type boolean
  2192.      */
  2193.     scroll: true,
  2194.     /**
  2195.      * Sets the pointer offset to the distance between the linked element's top
  2196.      * left corner and the location the element was clicked
  2197.      * @method autoOffset
  2198.      * @param {int} iPageX the X coordinate of the click
  2199.      * @param {int} iPageY the Y coordinate of the click
  2200.      */
  2201.     autoOffset: function(iPageX, iPageY) {
  2202.         var x = iPageX - this.startPageX;
  2203.         var y = iPageY - this.startPageY;
  2204.         this.setDelta(x, y);
  2205.     },
  2206.     /**
  2207.      * Sets the pointer offset.  You can call this directly to force the
  2208.      * offset to be in a particular location (e.g., pass in 0,0 to set it
  2209.      * to the center of the object)
  2210.      * @method setDelta
  2211.      * @param {int} iDeltaX the distance from the left
  2212.      * @param {int} iDeltaY the distance from the top
  2213.      */
  2214.     setDelta: function(iDeltaX, iDeltaY) {
  2215.         this.deltaX = iDeltaX;
  2216.         this.deltaY = iDeltaY;
  2217.     },
  2218.     /**
  2219.      * Sets the drag element to the location of the mousedown or click event,
  2220.      * maintaining the cursor location relative to the location on the element
  2221.      * that was clicked.  Override this if you want to place the element in a
  2222.      * location other than where the cursor is.
  2223.      * @method setDragElPos
  2224.      * @param {int} iPageX the X coordinate of the mousedown or drag event
  2225.      * @param {int} iPageY the Y coordinate of the mousedown or drag event
  2226.      */
  2227.     setDragElPos: function(iPageX, iPageY) {
  2228.         // the first time we do this, we are going to check to make sure
  2229.         // the element has css positioning
  2230.         var el = this.getDragEl();
  2231.         this.alignElWithMouse(el, iPageX, iPageY);
  2232.     },
  2233.     /**
  2234.      * Sets the element to the location of the mousedown or click event,
  2235.      * maintaining the cursor location relative to the location on the element
  2236.      * that was clicked.  Override this if you want to place the element in a
  2237.      * location other than where the cursor is.
  2238.      * @method alignElWithMouse
  2239.      * @param {HTMLElement} el the element to move
  2240.      * @param {int} iPageX the X coordinate of the mousedown or drag event
  2241.      * @param {int} iPageY the Y coordinate of the mousedown or drag event
  2242.      */
  2243.     alignElWithMouse: function(el, iPageX, iPageY) {
  2244.         var oCoord = this.getTargetCoord(iPageX, iPageY);
  2245.         var fly = el.dom ? el : Ext.fly(el, '_dd');
  2246.         if (!this.deltaSetXY) {
  2247.             var aCoord = [oCoord.x, oCoord.y];
  2248.             fly.setXY(aCoord);
  2249.             var newLeft = fly.getLeft(true);
  2250.             var newTop  = fly.getTop(true);
  2251.             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
  2252.         } else {
  2253.             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
  2254.         }
  2255.         this.cachePosition(oCoord.x, oCoord.y);
  2256.         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
  2257.         return oCoord;
  2258.     },
  2259.     /**
  2260.      * Saves the most recent position so that we can reset the constraints and
  2261.      * tick marks on-demand.  We need to know this so that we can calculate the
  2262.      * number of pixels the element is offset from its original position.
  2263.      * @method cachePosition
  2264.      * @param iPageX the current x position (optional, this just makes it so we
  2265.      * don't have to look it up again)
  2266.      * @param iPageY the current y position (optional, this just makes it so we
  2267.      * don't have to look it up again)
  2268.      */
  2269.     cachePosition: function(iPageX, iPageY) {
  2270.         if (iPageX) {
  2271.             this.lastPageX = iPageX;
  2272.             this.lastPageY = iPageY;
  2273.         } else {
  2274.             var aCoord = Ext.lib.Dom.getXY(this.getEl());
  2275.             this.lastPageX = aCoord[0];
  2276.             this.lastPageY = aCoord[1];
  2277.         }
  2278.     },
  2279.     /**
  2280.      * Auto-scroll the window if the dragged object has been moved beyond the
  2281.      * visible window boundary.
  2282.      * @method autoScroll
  2283.      * @param {int} x the drag element's x position
  2284.      * @param {int} y the drag element's y position
  2285.      * @param {int} h the height of the drag element
  2286.      * @param {int} w the width of the drag element
  2287.      * @private
  2288.      */
  2289.     autoScroll: function(x, y, h, w) {
  2290.         if (this.scroll) {
  2291.             // The client height
  2292.             var clientH = Ext.lib.Dom.getViewHeight();
  2293.             // The client width
  2294.             var clientW = Ext.lib.Dom.getViewWidth();
  2295.             // The amt scrolled down
  2296.             var st = this.DDM.getScrollTop();
  2297.             // The amt scrolled right
  2298.             var sl = this.DDM.getScrollLeft();
  2299.             // Location of the bottom of the element
  2300.             var bot = h + y;
  2301.             // Location of the right of the element
  2302.             var right = w + x;
  2303.             // The distance from the cursor to the bottom of the visible area,
  2304.             // adjusted so that we don't scroll if the cursor is beyond the
  2305.             // element drag constraints
  2306.             var toBot = (clientH + st - y - this.deltaY);
  2307.             // The distance from the cursor to the right of the visible area
  2308.             var toRight = (clientW + sl - x - this.deltaX);
  2309.             // How close to the edge the cursor must be before we scroll
  2310.             // var thresh = (document.all) ? 100 : 40;
  2311.             var thresh = 40;
  2312.             // How many pixels to scroll per autoscroll op.  This helps to reduce
  2313.             // clunky scrolling. IE is more sensitive about this ... it needs this
  2314.             // value to be higher.
  2315.             var scrAmt = (document.all) ? 80 : 30;
  2316.             // Scroll down if we are near the bottom of the visible page and the
  2317.             // obj extends below the crease
  2318.             if ( bot > clientH && toBot < thresh ) {
  2319.                 window.scrollTo(sl, st + scrAmt);
  2320.             }
  2321.             // Scroll up if the window is scrolled down and the top of the object
  2322.             // goes above the top border
  2323.             if ( y < st && st > 0 && y - st < thresh ) {
  2324.                 window.scrollTo(sl, st - scrAmt);
  2325.             }
  2326.             // Scroll right if the obj is beyond the right border and the cursor is
  2327.             // near the border.
  2328.             if ( right > clientW && toRight < thresh ) {
  2329.                 window.scrollTo(sl + scrAmt, st);
  2330.             }
  2331.             // Scroll left if the window has been scrolled to the right and the obj
  2332.             // extends past the left border
  2333.             if ( x < sl && sl > 0 && x - sl < thresh ) {
  2334.                 window.scrollTo(sl - scrAmt, st);
  2335.             }
  2336.         }
  2337.     },
  2338.     /**
  2339.      * Finds the location the element should be placed if we want to move
  2340.      * it to where the mouse location less the click offset would place us.
  2341.      * @method getTargetCoord
  2342.      * @param {int} iPageX the X coordinate of the click
  2343.      * @param {int} iPageY the Y coordinate of the click
  2344.      * @return an object that contains the coordinates (Object.x and Object.y)
  2345.      * @private
  2346.      */
  2347.     getTargetCoord: function(iPageX, iPageY) {
  2348.         var x = iPageX - this.deltaX;
  2349.         var y = iPageY - this.deltaY;
  2350.         if (this.constrainX) {
  2351.             if (x < this.minX) { x = this.minX; }
  2352.             if (x > this.maxX) { x = this.maxX; }
  2353.         }
  2354.         if (this.constrainY) {
  2355.             if (y < this.minY) { y = this.minY; }
  2356.             if (y > this.maxY) { y = this.maxY; }
  2357.         }
  2358.         x = this.getTick(x, this.xTicks);
  2359.         y = this.getTick(y, this.yTicks);
  2360.         return {x:x, y:y};
  2361.     },
  2362.     /**
  2363.      * Sets up config options specific to this class. Overrides
  2364.      * Ext.dd.DragDrop, but all versions of this method through the
  2365.      * inheritance chain are called
  2366.      */
  2367.     applyConfig: function() {
  2368.         Ext.dd.DD.superclass.applyConfig.call(this);
  2369.         this.scroll = (this.config.scroll !== false);
  2370.     },
  2371.     /**
  2372.      * Event that fires prior to the onMouseDown event.  Overrides
  2373.      * Ext.dd.DragDrop.
  2374.      */
  2375.     b4MouseDown: function(e) {
  2376.         // this.resetConstraints();
  2377.         this.autoOffset(e.getPageX(),
  2378.                             e.getPageY());
  2379.     },
  2380.     /**
  2381.      * Event that fires prior to the onDrag event.  Overrides
  2382.      * Ext.dd.DragDrop.
  2383.      */
  2384.     b4Drag: function(e) {
  2385.         this.setDragElPos(e.getPageX(),
  2386.                             e.getPageY());
  2387.     },
  2388.     toString: function() {
  2389.         return ("DD " + this.id);
  2390.     }
  2391.     //////////////////////////////////////////////////////////////////////////
  2392.     // Debugging ygDragDrop events that can be overridden
  2393.     //////////////////////////////////////////////////////////////////////////
  2394.     /*
  2395.     startDrag: function(x, y) {
  2396.     },
  2397.     onDrag: function(e) {
  2398.     },
  2399.     onDragEnter: function(e, id) {
  2400.     },
  2401.     onDragOver: function(e, id) {
  2402.     },
  2403.     onDragOut: function(e, id) {
  2404.     },
  2405.     onDragDrop: function(e, id) {
  2406.     },
  2407.     endDrag: function(e) {
  2408.     }
  2409.     */
  2410. });
  2411. /**
  2412.  * @class Ext.dd.DDProxy
  2413.  * A DragDrop implementation that inserts an empty, bordered div into
  2414.  * the document that follows the cursor during drag operations.  At the time of
  2415.  * the click, the frame div is resized to the dimensions of the linked html
  2416.  * element, and moved to the exact location of the linked element.
  2417.  *
  2418.  * References to the "frame" element refer to the single proxy element that
  2419.  * was created to be dragged in place of all DDProxy elements on the
  2420.  * page.
  2421.  *
  2422.  * @extends Ext.dd.DD
  2423.  * @constructor
  2424.  * @param {String} id the id of the linked html element
  2425.  * @param {String} sGroup the group of related DragDrop objects
  2426.  * @param {object} config an object containing configurable attributes
  2427.  *                Valid properties for DDProxy in addition to those in DragDrop:
  2428.  *                   resizeFrame, centerFrame, dragElId
  2429.  */
  2430. Ext.dd.DDProxy = function(id, sGroup, config) {
  2431.     if (id) {
  2432.         this.init(id, sGroup, config);
  2433.         this.initFrame();
  2434.     }
  2435. };
  2436. /**
  2437.  * The default drag frame div id
  2438.  * @property Ext.dd.DDProxy.dragElId
  2439.  * @type String
  2440.  * @static
  2441.  */
  2442. Ext.dd.DDProxy.dragElId = "ygddfdiv";
  2443. Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
  2444.     /**
  2445.      * By default we resize the drag frame to be the same size as the element
  2446.      * we want to drag (this is to get the frame effect).  We can turn it off
  2447.      * if we want a different behavior.
  2448.      * @property resizeFrame
  2449.      * @type boolean
  2450.      */
  2451.     resizeFrame: true,
  2452.     /**
  2453.      * By default the frame is positioned exactly where the drag element is, so
  2454.      * we use the cursor offset provided by Ext.dd.DD.  Another option that works only if
  2455.      * you do not have constraints on the obj is to have the drag frame centered
  2456.      * around the cursor.  Set centerFrame to true for this effect.
  2457.      * @property centerFrame
  2458.      * @type boolean
  2459.      */
  2460.     centerFrame: false,
  2461.     /**
  2462.      * Creates the proxy element if it does not yet exist
  2463.      * @method createFrame
  2464.      */
  2465.     createFrame: function() {
  2466.         var self = this;
  2467.         var body = document.body;
  2468.         if (!body || !body.firstChild) {
  2469.             setTimeout( function() { self.createFrame(); }, 50 );
  2470.             return;
  2471.         }
  2472.         var div = this.getDragEl();
  2473.         if (!div) {
  2474.             div    = document.createElement("div");
  2475.             div.id = this.dragElId;
  2476.             var s  = div.style;
  2477.             s.position   = "absolute";
  2478.             s.visibility = "hidden";
  2479.             s.cursor     = "move";
  2480.             s.border     = "2px solid #aaa";
  2481.             s.zIndex     = 999;
  2482.             // appendChild can blow up IE if invoked prior to the window load event
  2483.             // while rendering a table.  It is possible there are other scenarios
  2484.             // that would cause this to happen as well.
  2485.             body.insertBefore(div, body.firstChild);
  2486.         }
  2487.     },
  2488.     /**
  2489.      * Initialization for the drag frame element.  Must be called in the
  2490.      * constructor of all subclasses
  2491.      * @method initFrame
  2492.      */
  2493.     initFrame: function() {
  2494.         this.createFrame();
  2495.     },
  2496.     applyConfig: function() {
  2497.         Ext.dd.DDProxy.superclass.applyConfig.call(this);
  2498.         this.resizeFrame = (this.config.resizeFrame !== false);
  2499.         this.centerFrame = (this.config.centerFrame);
  2500.         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
  2501.     },
  2502.     /**
  2503.      * Resizes the drag frame to the dimensions of the clicked object, positions
  2504.      * it over the object, and finally displays it
  2505.      * @method showFrame
  2506.      * @param {int} iPageX X click position
  2507.      * @param {int} iPageY Y click position
  2508.      * @private
  2509.      */
  2510.     showFrame: function(iPageX, iPageY) {
  2511.         var el = this.getEl();
  2512.         var dragEl = this.getDragEl();
  2513.         var s = dragEl.style;
  2514.         this._resizeProxy();
  2515.         if (this.centerFrame) {
  2516.             this.setDelta( Math.round(parseInt(s.width,  10)/2),
  2517.                            Math.round(parseInt(s.height, 10)/2) );
  2518.         }
  2519.         this.setDragElPos(iPageX, iPageY);
  2520.         Ext.fly(dragEl).show();
  2521.     },
  2522.     /**
  2523.      * The proxy is automatically resized to the dimensions of the linked
  2524.      * element when a drag is initiated, unless resizeFrame is set to false
  2525.      * @method _resizeProxy
  2526.      * @private
  2527.      */
  2528.     _resizeProxy: function() {
  2529.         if (this.resizeFrame) {
  2530.             var el = this.getEl();
  2531.             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
  2532.         }
  2533.     },
  2534.     // overrides Ext.dd.DragDrop
  2535.     b4MouseDown: function(e) {
  2536.         var x = e.getPageX();
  2537.         var y = e.getPageY();
  2538.         this.autoOffset(x, y);
  2539.         this.setDragElPos(x, y);
  2540.     },
  2541.     // overrides Ext.dd.DragDrop
  2542.     b4StartDrag: function(x, y) {
  2543.         // show the drag frame
  2544.         this.showFrame(x, y);
  2545.     },
  2546.     // overrides Ext.dd.DragDrop
  2547.     b4EndDrag: function(e) {
  2548.         Ext.fly(this.getDragEl()).hide();
  2549.     },
  2550.     // overrides Ext.dd.DragDrop
  2551.     // By default we try to move the element to the last location of the frame.
  2552.     // This is so that the default behavior mirrors that of Ext.dd.DD.
  2553.     endDrag: function(e) {
  2554.         var lel = this.getEl();
  2555.         var del = this.getDragEl();
  2556.         // Show the drag frame briefly so we can get its position
  2557.         del.style.visibility = "";
  2558.         this.beforeMove();
  2559.         // Hide the linked element before the move to get around a Safari
  2560.         // rendering bug.
  2561.         lel.style.visibility = "hidden";
  2562.         Ext.dd.DDM.moveToEl(lel, del);
  2563.         del.style.visibility = "hidden";
  2564.         lel.style.visibility = "";
  2565.         this.afterDrag();
  2566.     },
  2567.     beforeMove : function(){
  2568.     },
  2569.     afterDrag : function(){
  2570.     },
  2571.     toString: function() {
  2572.         return ("DDProxy " + this.id);
  2573.     }
  2574. });
  2575. /**
  2576.  * @class Ext.dd.DDTarget
  2577.  * A DragDrop implementation that does not move, but can be a drop
  2578.  * target.  You would get the same result by simply omitting implementation
  2579.  * for the event callbacks, but this way we reduce the processing cost of the
  2580.  * event listener and the callbacks.
  2581.  * @extends Ext.dd.DragDrop
  2582.  * @constructor
  2583.  * @param {String} id the id of the element that is a drop target
  2584.  * @param {String} sGroup the group of related DragDrop objects
  2585.  * @param {object} config an object containing configurable attributes
  2586.  *                 Valid properties for DDTarget in addition to those in
  2587.  *                 DragDrop:
  2588.  *                    none
  2589.  */
  2590. Ext.dd.DDTarget = function(id, sGroup, config) {
  2591.     if (id) {
  2592.         this.initTarget(id, sGroup, config);
  2593.     }
  2594. };
  2595. // Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();
  2596. Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
  2597.     toString: function() {
  2598.         return ("DDTarget " + this.id);
  2599.     }
  2600. });