PageRenderTime 58ms CodeModel.GetById 12ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/javascripts/lib/src/dd/DDCore.js

https://bitbucket.org/ksokmesa/sina-asian
JavaScript | 3158 lines | 1132 code | 380 blank | 1646 comment | 232 complexity | 6352ccaa30807bab7b5f15d830e833c0 MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

   1/*!
   2 * Ext JS Library 3.2.1
   3 * Copyright(c) 2006-2010 Ext JS, Inc.
   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
  15(function() {
  16
  17var Event=Ext.EventManager;
  18var Dom=Ext.lib.Dom;
  19
  20/**
  21 * @class Ext.dd.DragDrop
  22 * Defines the interface and base operation of items that that can be
  23 * dragged or can be drop targets.  It was designed to be extended, overriding
  24 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
  25 * Up to three html elements can be associated with a DragDrop instance:
  26 * <ul>
  27 * <li>linked element: the element that is passed into the constructor.
  28 * This is the element which defines the boundaries for interaction with
  29 * other DragDrop objects.</li>
  30 * <li>handle element(s): The drag operation only occurs if the element that
  31 * was clicked matches a handle element.  By default this is the linked
  32 * element, but there are times that you will want only a portion of the
  33 * linked element to initiate the drag operation, and the setHandleElId()
  34 * method provides a way to define this.</li>
  35 * <li>drag element: this represents the element that would be moved along
  36 * with the cursor during a drag operation.  By default, this is the linked
  37 * element itself as in {@link Ext.dd.DD}.  setDragElId() lets you define
  38 * a separate element that would be moved, as in {@link Ext.dd.DDProxy}.
  39 * </li>
  40 * </ul>
  41 * This class should not be instantiated until the onload event to ensure that
  42 * the associated elements are available.
  43 * The following would define a DragDrop obj that would interact with any
  44 * other DragDrop obj in the "group1" group:
  45 * <pre>
  46 *  dd = new Ext.dd.DragDrop("div1", "group1");
  47 * </pre>
  48 * Since none of the event handlers have been implemented, nothing would
  49 * actually happen if you were to run the code above.  Normally you would
  50 * override this class or one of the default implementations, but you can
  51 * also override the methods you want on an instance of the class...
  52 * <pre>
  53 *  dd.onDragDrop = function(e, id) {
  54 *  &nbsp;&nbsp;alert("dd was dropped on " + id);
  55 *  }
  56 * </pre>
  57 * @constructor
  58 * @param {String} id of the element that is linked to this instance
  59 * @param {String} sGroup the group of related DragDrop objects
  60 * @param {object} config an object containing configurable attributes
  61 *                Valid properties for DragDrop:
  62 *                    padding, isTarget, maintainOffset, primaryButtonOnly
  63 */
  64Ext.dd.DragDrop = function(id, sGroup, config) {
  65    if(id) {
  66        this.init(id, sGroup, config);
  67    }
  68};
  69
  70Ext.dd.DragDrop.prototype = {
  71
  72    /**
  73     * Set to false to enable a DragDrop object to fire drag events while dragging
  74     * over its own Element. Defaults to true - DragDrop objects do not by default
  75     * fire drag events to themselves.
  76     * @property ignoreSelf
  77     * @type Boolean
  78     */
  79
  80    /**
  81     * The id of the element associated with this object.  This is what we
  82     * refer to as the "linked element" because the size and position of
  83     * this element is used to determine when the drag and drop objects have
  84     * interacted.
  85     * @property id
  86     * @type String
  87     */
  88    id: null,
  89
  90    /**
  91     * Configuration attributes passed into the constructor
  92     * @property config
  93     * @type object
  94     */
  95    config: null,
  96
  97    /**
  98     * The id of the element that will be dragged.  By default this is same
  99     * as the linked element, but could be changed to another element. Ex:
 100     * Ext.dd.DDProxy
 101     * @property dragElId
 102     * @type String
 103     * @private
 104     */
 105    dragElId: null,
 106
 107    /**
 108     * The ID of the element that initiates the drag operation.  By default
 109     * this is the linked element, but could be changed to be a child of this
 110     * element.  This lets us do things like only starting the drag when the
 111     * header element within the linked html element is clicked.
 112     * @property handleElId
 113     * @type String
 114     * @private
 115     */
 116    handleElId: null,
 117
 118    /**
 119     * An object who's property names identify HTML tags to be considered invalid as drag handles.
 120     * A non-null property value identifies the tag as invalid. Defaults to the 
 121     * following value which prevents drag operations from being initiated by &lt;a> elements:<pre><code>
 122{
 123    A: "A"
 124}</code></pre>
 125     * @property invalidHandleTypes
 126     * @type Object
 127     */
 128    invalidHandleTypes: null,
 129
 130    /**
 131     * An object who's property names identify the IDs of elements to be considered invalid as drag handles.
 132     * A non-null property value identifies the ID as invalid. For example, to prevent
 133     * dragging from being initiated on element ID "foo", use:<pre><code>
 134{
 135    foo: true
 136}</code></pre>
 137     * @property invalidHandleIds
 138     * @type Object
 139     */
 140    invalidHandleIds: null,
 141
 142    /**
 143     * An Array of CSS class names for elements to be considered in valid as drag handles.
 144     * @property invalidHandleClasses
 145     * @type Array
 146     */
 147    invalidHandleClasses: null,
 148
 149    /**
 150     * The linked element's absolute X position at the time the drag was
 151     * started
 152     * @property startPageX
 153     * @type int
 154     * @private
 155     */
 156    startPageX: 0,
 157
 158    /**
 159     * The linked element's absolute X position at the time the drag was
 160     * started
 161     * @property startPageY
 162     * @type int
 163     * @private
 164     */
 165    startPageY: 0,
 166
 167    /**
 168     * The group defines a logical collection of DragDrop objects that are
 169     * related.  Instances only get events when interacting with other
 170     * DragDrop object in the same group.  This lets us define multiple
 171     * groups using a single DragDrop subclass if we want.
 172     * @property groups
 173     * @type object An object in the format {'group1':true, 'group2':true}
 174     */
 175    groups: null,
 176
 177    /**
 178     * Individual drag/drop instances can be locked.  This will prevent
 179     * onmousedown start drag.
 180     * @property locked
 181     * @type boolean
 182     * @private
 183     */
 184    locked: false,
 185
 186    /**
 187     * Lock this instance
 188     * @method lock
 189     */
 190    lock: function() {
 191        this.locked = true;
 192    },
 193
 194    /**
 195     * When set to true, other DD objects in cooperating DDGroups do not receive
 196     * notification events when this DD object is dragged over them. Defaults to false.
 197     * @property moveOnly
 198     * @type boolean
 199     */
 200    moveOnly: false,
 201
 202    /**
 203     * Unlock this instace
 204     * @method unlock
 205     */
 206    unlock: function() {
 207        this.locked = false;
 208    },
 209
 210    /**
 211     * By default, all instances can be a drop target.  This can be disabled by
 212     * setting isTarget to false.
 213     * @property isTarget
 214     * @type boolean
 215     */
 216    isTarget: true,
 217
 218    /**
 219     * The padding configured for this drag and drop object for calculating
 220     * the drop zone intersection with this object.
 221     * @property padding
 222     * @type int[] An array containing the 4 padding values: [top, right, bottom, left]
 223     */
 224    padding: null,
 225
 226    /**
 227     * Cached reference to the linked element
 228     * @property _domRef
 229     * @private
 230     */
 231    _domRef: null,
 232
 233    /**
 234     * Internal typeof flag
 235     * @property __ygDragDrop
 236     * @private
 237     */
 238    __ygDragDrop: true,
 239
 240    /**
 241     * Set to true when horizontal contraints are applied
 242     * @property constrainX
 243     * @type boolean
 244     * @private
 245     */
 246    constrainX: false,
 247
 248    /**
 249     * Set to true when vertical contraints are applied
 250     * @property constrainY
 251     * @type boolean
 252     * @private
 253     */
 254    constrainY: false,
 255
 256    /**
 257     * The left constraint
 258     * @property minX
 259     * @type int
 260     * @private
 261     */
 262    minX: 0,
 263
 264    /**
 265     * The right constraint
 266     * @property maxX
 267     * @type int
 268     * @private
 269     */
 270    maxX: 0,
 271
 272    /**
 273     * The up constraint
 274     * @property minY
 275     * @type int
 276     * @private
 277     */
 278    minY: 0,
 279
 280    /**
 281     * The down constraint
 282     * @property maxY
 283     * @type int
 284     * @private
 285     */
 286    maxY: 0,
 287
 288    /**
 289     * Maintain offsets when we resetconstraints.  Set to true when you want
 290     * the position of the element relative to its parent to stay the same
 291     * when the page changes
 292     *
 293     * @property maintainOffset
 294     * @type boolean
 295     */
 296    maintainOffset: false,
 297
 298    /**
 299     * Array of pixel locations the element will snap to if we specified a
 300     * horizontal graduation/interval.  This array is generated automatically
 301     * when you define a tick interval.
 302     * @property xTicks
 303     * @type int[]
 304     */
 305    xTicks: null,
 306
 307    /**
 308     * Array of pixel locations the element will snap to if we specified a
 309     * vertical graduation/interval.  This array is generated automatically
 310     * when you define a tick interval.
 311     * @property yTicks
 312     * @type int[]
 313     */
 314    yTicks: null,
 315
 316    /**
 317     * By default the drag and drop instance will only respond to the primary
 318     * button click (left button for a right-handed mouse).  Set to true to
 319     * allow drag and drop to start with any mouse click that is propogated
 320     * by the browser
 321     * @property primaryButtonOnly
 322     * @type boolean
 323     */
 324    primaryButtonOnly: true,
 325
 326    /**
 327     * The available property is false until the linked dom element is accessible.
 328     * @property available
 329     * @type boolean
 330     */
 331    available: false,
 332
 333    /**
 334     * By default, drags can only be initiated if the mousedown occurs in the
 335     * region the linked element is.  This is done in part to work around a
 336     * bug in some browsers that mis-report the mousedown if the previous
 337     * mouseup happened outside of the window.  This property is set to true
 338     * if outer handles are defined.
 339     *
 340     * @property hasOuterHandles
 341     * @type boolean
 342     * @default false
 343     */
 344    hasOuterHandles: false,
 345
 346    /**
 347     * Code that executes immediately before the startDrag event
 348     * @method b4StartDrag
 349     * @private
 350     */
 351    b4StartDrag: function(x, y) { },
 352
 353    /**
 354     * Abstract method called after a drag/drop object is clicked
 355     * and the drag or mousedown time thresholds have beeen met.
 356     * @method startDrag
 357     * @param {int} X click location
 358     * @param {int} Y click location
 359     */
 360    startDrag: function(x, y) { /* override this */ },
 361
 362    /**
 363     * Code that executes immediately before the onDrag event
 364     * @method b4Drag
 365     * @private
 366     */
 367    b4Drag: function(e) { },
 368
 369    /**
 370     * Abstract method called during the onMouseMove event while dragging an
 371     * object.
 372     * @method onDrag
 373     * @param {Event} e the mousemove event
 374     */
 375    onDrag: function(e) { /* override this */ },
 376
 377    /**
 378     * Abstract method called when this element fist begins hovering over
 379     * another DragDrop obj
 380     * @method onDragEnter
 381     * @param {Event} e the mousemove event
 382     * @param {String|DragDrop[]} id In POINT mode, the element
 383     * id this is hovering over.  In INTERSECT mode, an array of one or more
 384     * dragdrop items being hovered over.
 385     */
 386    onDragEnter: function(e, id) { /* override this */ },
 387
 388    /**
 389     * Code that executes immediately before the onDragOver event
 390     * @method b4DragOver
 391     * @private
 392     */
 393    b4DragOver: function(e) { },
 394
 395    /**
 396     * Abstract method called when this element is hovering over another
 397     * DragDrop obj
 398     * @method onDragOver
 399     * @param {Event} e the mousemove event
 400     * @param {String|DragDrop[]} id In POINT mode, the element
 401     * id this is hovering over.  In INTERSECT mode, an array of dd items
 402     * being hovered over.
 403     */
 404    onDragOver: function(e, id) { /* override this */ },
 405
 406    /**
 407     * Code that executes immediately before the onDragOut event
 408     * @method b4DragOut
 409     * @private
 410     */
 411    b4DragOut: function(e) { },
 412
 413    /**
 414     * Abstract method called when we are no longer hovering over an element
 415     * @method onDragOut
 416     * @param {Event} e the mousemove event
 417     * @param {String|DragDrop[]} id In POINT mode, the element
 418     * id this was hovering over.  In INTERSECT mode, an array of dd items
 419     * that the mouse is no longer over.
 420     */
 421    onDragOut: function(e, id) { /* override this */ },
 422
 423    /**
 424     * Code that executes immediately before the onDragDrop event
 425     * @method b4DragDrop
 426     * @private
 427     */
 428    b4DragDrop: function(e) { },
 429
 430    /**
 431     * Abstract method called when this item is dropped on another DragDrop
 432     * obj
 433     * @method onDragDrop
 434     * @param {Event} e the mouseup event
 435     * @param {String|DragDrop[]} id In POINT mode, the element
 436     * id this was dropped on.  In INTERSECT mode, an array of dd items this
 437     * was dropped on.
 438     */
 439    onDragDrop: function(e, id) { /* override this */ },
 440
 441    /**
 442     * Abstract method called when this item is dropped on an area with no
 443     * drop target
 444     * @method onInvalidDrop
 445     * @param {Event} e the mouseup event
 446     */
 447    onInvalidDrop: function(e) { /* override this */ },
 448
 449    /**
 450     * Code that executes immediately before the endDrag event
 451     * @method b4EndDrag
 452     * @private
 453     */
 454    b4EndDrag: function(e) { },
 455
 456    /**
 457     * Fired when we are done dragging the object
 458     * @method endDrag
 459     * @param {Event} e the mouseup event
 460     */
 461    endDrag: function(e) { /* override this */ },
 462
 463    /**
 464     * Code executed immediately before the onMouseDown event
 465     * @method b4MouseDown
 466     * @param {Event} e the mousedown event
 467     * @private
 468     */
 469    b4MouseDown: function(e) {  },
 470
 471    /**
 472     * Event handler that fires when a drag/drop obj gets a mousedown
 473     * @method onMouseDown
 474     * @param {Event} e the mousedown event
 475     */
 476    onMouseDown: function(e) { /* override this */ },
 477
 478    /**
 479     * Event handler that fires when a drag/drop obj gets a mouseup
 480     * @method onMouseUp
 481     * @param {Event} e the mouseup event
 482     */
 483    onMouseUp: function(e) { /* override this */ },
 484
 485    /**
 486     * Override the onAvailable method to do what is needed after the initial
 487     * position was determined.
 488     * @method onAvailable
 489     */
 490    onAvailable: function () {
 491    },
 492
 493    /**
 494     * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
 495     * @type Object
 496     */
 497    defaultPadding : {left:0, right:0, top:0, bottom:0},
 498
 499    /**
 500     * Initializes the drag drop object's constraints to restrict movement to a certain element.
 501 *
 502 * Usage:
 503 <pre><code>
 504 var dd = new Ext.dd.DDProxy("dragDiv1", "proxytest",
 505                { dragElId: "existingProxyDiv" });
 506 dd.startDrag = function(){
 507     this.constrainTo("parent-id");
 508 };
 509 </code></pre>
 510 * Or you can initalize it using the {@link Ext.Element} object:
 511 <pre><code>
 512 Ext.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
 513     startDrag : function(){
 514         this.constrainTo("parent-id");
 515     }
 516 });
 517 </code></pre>
 518     * @param {Mixed} constrainTo The element to constrain to.
 519     * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
 520     * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
 521     * an object containing the sides to pad. For example: {right:10, bottom:10}
 522     * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
 523     */
 524    constrainTo : function(constrainTo, pad, inContent){
 525        if(Ext.isNumber(pad)){
 526            pad = {left: pad, right:pad, top:pad, bottom:pad};
 527        }
 528        pad = pad || this.defaultPadding;
 529        var b = Ext.get(this.getEl()).getBox(),
 530            ce = Ext.get(constrainTo),
 531            s = ce.getScroll(),
 532            c, 
 533            cd = ce.dom;
 534        if(cd == document.body){
 535            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
 536        }else{
 537            var xy = ce.getXY();
 538            c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
 539        }
 540
 541
 542        var topSpace = b.y - c.y,
 543            leftSpace = b.x - c.x;
 544
 545        this.resetConstraints();
 546        this.setXConstraint(leftSpace - (pad.left||0), // left
 547                c.width - leftSpace - b.width - (pad.right||0), //right
 548				this.xTickSize
 549        );
 550        this.setYConstraint(topSpace - (pad.top||0), //top
 551                c.height - topSpace - b.height - (pad.bottom||0), //bottom
 552				this.yTickSize
 553        );
 554    },
 555
 556    /**
 557     * Returns a reference to the linked element
 558     * @method getEl
 559     * @return {HTMLElement} the html element
 560     */
 561    getEl: function() {
 562        if (!this._domRef) {
 563            this._domRef = Ext.getDom(this.id);
 564        }
 565
 566        return this._domRef;
 567    },
 568
 569    /**
 570     * Returns a reference to the actual element to drag.  By default this is
 571     * the same as the html element, but it can be assigned to another
 572     * element. An example of this can be found in Ext.dd.DDProxy
 573     * @method getDragEl
 574     * @return {HTMLElement} the html element
 575     */
 576    getDragEl: function() {
 577        return Ext.getDom(this.dragElId);
 578    },
 579
 580    /**
 581     * Sets up the DragDrop object.  Must be called in the constructor of any
 582     * Ext.dd.DragDrop subclass
 583     * @method init
 584     * @param id the id of the linked element
 585     * @param {String} sGroup the group of related items
 586     * @param {object} config configuration attributes
 587     */
 588    init: function(id, sGroup, config) {
 589        this.initTarget(id, sGroup, config);
 590        Event.on(this.id, "mousedown", this.handleMouseDown, this);
 591        // Event.on(this.id, "selectstart", Event.preventDefault);
 592    },
 593
 594    /**
 595     * Initializes Targeting functionality only... the object does not
 596     * get a mousedown handler.
 597     * @method initTarget
 598     * @param id the id of the linked element
 599     * @param {String} sGroup the group of related items
 600     * @param {object} config configuration attributes
 601     */
 602    initTarget: function(id, sGroup, config) {
 603
 604        // configuration attributes
 605        this.config = config || {};
 606
 607        // create a local reference to the drag and drop manager
 608        this.DDM = Ext.dd.DDM;
 609        // initialize the groups array
 610        this.groups = {};
 611
 612        // assume that we have an element reference instead of an id if the
 613        // parameter is not a string
 614        if (typeof id !== "string") {
 615            id = Ext.id(id);
 616        }
 617
 618        // set the id
 619        this.id = id;
 620
 621        // add to an interaction group
 622        this.addToGroup((sGroup) ? sGroup : "default");
 623
 624        // We don't want to register this as the handle with the manager
 625        // so we just set the id rather than calling the setter.
 626        this.handleElId = id;
 627
 628        // the linked element is the element that gets dragged by default
 629        this.setDragElId(id);
 630
 631        // by default, clicked anchors will not start drag operations.
 632        this.invalidHandleTypes = { A: "A" };
 633        this.invalidHandleIds = {};
 634        this.invalidHandleClasses = [];
 635
 636        this.applyConfig();
 637
 638        this.handleOnAvailable();
 639    },
 640
 641    /**
 642     * Applies the configuration parameters that were passed into the constructor.
 643     * This is supposed to happen at each level through the inheritance chain.  So
 644     * a DDProxy implentation will execute apply config on DDProxy, DD, and
 645     * DragDrop in order to get all of the parameters that are available in
 646     * each object.
 647     * @method applyConfig
 648     */
 649    applyConfig: function() {
 650
 651        // configurable properties:
 652        //    padding, isTarget, maintainOffset, primaryButtonOnly
 653        this.padding           = this.config.padding || [0, 0, 0, 0];
 654        this.isTarget          = (this.config.isTarget !== false);
 655        this.maintainOffset    = (this.config.maintainOffset);
 656        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
 657
 658    },
 659
 660    /**
 661     * Executed when the linked element is available
 662     * @method handleOnAvailable
 663     * @private
 664     */
 665    handleOnAvailable: function() {
 666        this.available = true;
 667        this.resetConstraints();
 668        this.onAvailable();
 669    },
 670
 671     /**
 672     * Configures the padding for the target zone in px.  Effectively expands
 673     * (or reduces) the virtual object size for targeting calculations.
 674     * Supports css-style shorthand; if only one parameter is passed, all sides
 675     * will have that padding, and if only two are passed, the top and bottom
 676     * will have the first param, the left and right the second.
 677     * @method setPadding
 678     * @param {int} iTop    Top pad
 679     * @param {int} iRight  Right pad
 680     * @param {int} iBot    Bot pad
 681     * @param {int} iLeft   Left pad
 682     */
 683    setPadding: function(iTop, iRight, iBot, iLeft) {
 684        // this.padding = [iLeft, iRight, iTop, iBot];
 685        if (!iRight && 0 !== iRight) {
 686            this.padding = [iTop, iTop, iTop, iTop];
 687        } else if (!iBot && 0 !== iBot) {
 688            this.padding = [iTop, iRight, iTop, iRight];
 689        } else {
 690            this.padding = [iTop, iRight, iBot, iLeft];
 691        }
 692    },
 693
 694    /**
 695     * Stores the initial placement of the linked element.
 696     * @method setInitPosition
 697     * @param {int} diffX   the X offset, default 0
 698     * @param {int} diffY   the Y offset, default 0
 699     */
 700    setInitPosition: function(diffX, diffY) {
 701        var el = this.getEl();
 702
 703        if (!this.DDM.verifyEl(el)) {
 704            return;
 705        }
 706
 707        var dx = diffX || 0;
 708        var dy = diffY || 0;
 709
 710        var p = Dom.getXY( el );
 711
 712        this.initPageX = p[0] - dx;
 713        this.initPageY = p[1] - dy;
 714
 715        this.lastPageX = p[0];
 716        this.lastPageY = p[1];
 717
 718        this.setStartPosition(p);
 719    },
 720
 721    /**
 722     * Sets the start position of the element.  This is set when the obj
 723     * is initialized, the reset when a drag is started.
 724     * @method setStartPosition
 725     * @param pos current position (from previous lookup)
 726     * @private
 727     */
 728    setStartPosition: function(pos) {
 729        var p = pos || Dom.getXY( this.getEl() );
 730        this.deltaSetXY = null;
 731
 732        this.startPageX = p[0];
 733        this.startPageY = p[1];
 734    },
 735
 736    /**
 737     * Add this instance to a group of related drag/drop objects.  All
 738     * instances belong to at least one group, and can belong to as many
 739     * groups as needed.
 740     * @method addToGroup
 741     * @param sGroup {string} the name of the group
 742     */
 743    addToGroup: function(sGroup) {
 744        this.groups[sGroup] = true;
 745        this.DDM.regDragDrop(this, sGroup);
 746    },
 747
 748    /**
 749     * Remove's this instance from the supplied interaction group
 750     * @method removeFromGroup
 751     * @param {string}  sGroup  The group to drop
 752     */
 753    removeFromGroup: function(sGroup) {
 754        if (this.groups[sGroup]) {
 755            delete this.groups[sGroup];
 756        }
 757
 758        this.DDM.removeDDFromGroup(this, sGroup);
 759    },
 760
 761    /**
 762     * Allows you to specify that an element other than the linked element
 763     * will be moved with the cursor during a drag
 764     * @method setDragElId
 765     * @param id {string} the id of the element that will be used to initiate the drag
 766     */
 767    setDragElId: function(id) {
 768        this.dragElId = id;
 769    },
 770
 771    /**
 772     * Allows you to specify a child of the linked element that should be
 773     * used to initiate the drag operation.  An example of this would be if
 774     * you have a content div with text and links.  Clicking anywhere in the
 775     * content area would normally start the drag operation.  Use this method
 776     * to specify that an element inside of the content div is the element
 777     * that starts the drag operation.
 778     * @method setHandleElId
 779     * @param id {string} the id of the element that will be used to
 780     * initiate the drag.
 781     */
 782    setHandleElId: function(id) {
 783        if (typeof id !== "string") {
 784            id = Ext.id(id);
 785        }
 786        this.handleElId = id;
 787        this.DDM.regHandle(this.id, id);
 788    },
 789
 790    /**
 791     * Allows you to set an element outside of the linked element as a drag
 792     * handle
 793     * @method setOuterHandleElId
 794     * @param id the id of the element that will be used to initiate the drag
 795     */
 796    setOuterHandleElId: function(id) {
 797        if (typeof id !== "string") {
 798            id = Ext.id(id);
 799        }
 800        Event.on(id, "mousedown",
 801                this.handleMouseDown, this);
 802        this.setHandleElId(id);
 803
 804        this.hasOuterHandles = true;
 805    },
 806
 807    /**
 808     * Remove all drag and drop hooks for this element
 809     * @method unreg
 810     */
 811    unreg: function() {
 812        Event.un(this.id, "mousedown",
 813                this.handleMouseDown);
 814        this._domRef = null;
 815        this.DDM._remove(this);
 816    },
 817
 818    destroy : function(){
 819        this.unreg();
 820    },
 821
 822    /**
 823     * Returns true if this instance is locked, or the drag drop mgr is locked
 824     * (meaning that all drag/drop is disabled on the page.)
 825     * @method isLocked
 826     * @return {boolean} true if this obj or all drag/drop is locked, else
 827     * false
 828     */
 829    isLocked: function() {
 830        return (this.DDM.isLocked() || this.locked);
 831    },
 832
 833    /**
 834     * Fired when this object is clicked
 835     * @method handleMouseDown
 836     * @param {Event} e
 837     * @param {Ext.dd.DragDrop} oDD the clicked dd object (this dd obj)
 838     * @private
 839     */
 840    handleMouseDown: function(e, oDD){
 841        if (this.primaryButtonOnly && e.button != 0) {
 842            return;
 843        }
 844
 845        if (this.isLocked()) {
 846            return;
 847        }
 848
 849        this.DDM.refreshCache(this.groups);
 850
 851        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
 852        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
 853        } else {
 854            if (this.clickValidator(e)) {
 855
 856                // set the initial element position
 857                this.setStartPosition();
 858
 859                this.b4MouseDown(e);
 860                this.onMouseDown(e);
 861
 862                this.DDM.handleMouseDown(e, this);
 863
 864                this.DDM.stopEvent(e);
 865            } else {
 866
 867
 868            }
 869        }
 870    },
 871
 872    clickValidator: function(e) {
 873        var target = e.getTarget();
 874        return ( this.isValidHandleChild(target) &&
 875                    (this.id == this.handleElId ||
 876                        this.DDM.handleWasClicked(target, this.id)) );
 877    },
 878
 879    /**
 880     * Allows you to specify a tag name that should not start a drag operation
 881     * when clicked.  This is designed to facilitate embedding links within a
 882     * drag handle that do something other than start the drag.
 883     * @method addInvalidHandleType
 884     * @param {string} tagName the type of element to exclude
 885     */
 886    addInvalidHandleType: function(tagName) {
 887        var type = tagName.toUpperCase();
 888        this.invalidHandleTypes[type] = type;
 889    },
 890
 891    /**
 892     * Lets you to specify an element id for a child of a drag handle
 893     * that should not initiate a drag
 894     * @method addInvalidHandleId
 895     * @param {string} id the element id of the element you wish to ignore
 896     */
 897    addInvalidHandleId: function(id) {
 898        if (typeof id !== "string") {
 899            id = Ext.id(id);
 900        }
 901        this.invalidHandleIds[id] = id;
 902    },
 903
 904    /**
 905     * Lets you specify a css class of elements that will not initiate a drag
 906     * @method addInvalidHandleClass
 907     * @param {string} cssClass the class of the elements you wish to ignore
 908     */
 909    addInvalidHandleClass: function(cssClass) {
 910        this.invalidHandleClasses.push(cssClass);
 911    },
 912
 913    /**
 914     * Unsets an excluded tag name set by addInvalidHandleType
 915     * @method removeInvalidHandleType
 916     * @param {string} tagName the type of element to unexclude
 917     */
 918    removeInvalidHandleType: function(tagName) {
 919        var type = tagName.toUpperCase();
 920        // this.invalidHandleTypes[type] = null;
 921        delete this.invalidHandleTypes[type];
 922    },
 923
 924    /**
 925     * Unsets an invalid handle id
 926     * @method removeInvalidHandleId
 927     * @param {string} id the id of the element to re-enable
 928     */
 929    removeInvalidHandleId: function(id) {
 930        if (typeof id !== "string") {
 931            id = Ext.id(id);
 932        }
 933        delete this.invalidHandleIds[id];
 934    },
 935
 936    /**
 937     * Unsets an invalid css class
 938     * @method removeInvalidHandleClass
 939     * @param {string} cssClass the class of the element(s) you wish to
 940     * re-enable
 941     */
 942    removeInvalidHandleClass: function(cssClass) {
 943        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
 944            if (this.invalidHandleClasses[i] == cssClass) {
 945                delete this.invalidHandleClasses[i];
 946            }
 947        }
 948    },
 949
 950    /**
 951     * Checks the tag exclusion list to see if this click should be ignored
 952     * @method isValidHandleChild
 953     * @param {HTMLElement} node the HTMLElement to evaluate
 954     * @return {boolean} true if this is a valid tag type, false if not
 955     */
 956    isValidHandleChild: function(node) {
 957
 958        var valid = true;
 959        // var n = (node.nodeName == "#text") ? node.parentNode : node;
 960        var nodeName;
 961        try {
 962            nodeName = node.nodeName.toUpperCase();
 963        } catch(e) {
 964            nodeName = node.nodeName;
 965        }
 966        valid = valid && !this.invalidHandleTypes[nodeName];
 967        valid = valid && !this.invalidHandleIds[node.id];
 968
 969        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
 970            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
 971        }
 972
 973
 974        return valid;
 975
 976    },
 977
 978    /**
 979     * Create the array of horizontal tick marks if an interval was specified
 980     * in setXConstraint().
 981     * @method setXTicks
 982     * @private
 983     */
 984    setXTicks: function(iStartX, iTickSize) {
 985        this.xTicks = [];
 986        this.xTickSize = iTickSize;
 987
 988        var tickMap = {};
 989
 990        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
 991            if (!tickMap[i]) {
 992                this.xTicks[this.xTicks.length] = i;
 993                tickMap[i] = true;
 994            }
 995        }
 996
 997        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
 998            if (!tickMap[i]) {
 999                this.xTicks[this.xTicks.length] = i;
1000                tickMap[i] = true;
1001            }
1002        }
1003
1004        this.xTicks.sort(this.DDM.numericSort) ;
1005    },
1006
1007    /**
1008     * Create the array of vertical tick marks if an interval was specified in
1009     * setYConstraint().
1010     * @method setYTicks
1011     * @private
1012     */
1013    setYTicks: function(iStartY, iTickSize) {
1014        this.yTicks = [];
1015        this.yTickSize = iTickSize;
1016
1017        var tickMap = {};
1018
1019        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
1020            if (!tickMap[i]) {
1021                this.yTicks[this.yTicks.length] = i;
1022                tickMap[i] = true;
1023            }
1024        }
1025
1026        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
1027            if (!tickMap[i]) {
1028                this.yTicks[this.yTicks.length] = i;
1029                tickMap[i] = true;
1030            }
1031        }
1032
1033        this.yTicks.sort(this.DDM.numericSort) ;
1034    },
1035
1036    /**
1037     * By default, the element can be dragged any place on the screen.  Use
1038     * this method to limit the horizontal travel of the element.  Pass in
1039     * 0,0 for the parameters if you want to lock the drag to the y axis.
1040     * @method setXConstraint
1041     * @param {int} iLeft the number of pixels the element can move to the left
1042     * @param {int} iRight the number of pixels the element can move to the
1043     * right
1044     * @param {int} iTickSize optional parameter for specifying that the
1045     * element
1046     * should move iTickSize pixels at a time.
1047     */
1048    setXConstraint: function(iLeft, iRight, iTickSize) {
1049        this.leftConstraint = iLeft;
1050        this.rightConstraint = iRight;
1051
1052        this.minX = this.initPageX - iLeft;
1053        this.maxX = this.initPageX + iRight;
1054        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
1055
1056        this.constrainX = true;
1057    },
1058
1059    /**
1060     * Clears any constraints applied to this instance.  Also clears ticks
1061     * since they can't exist independent of a constraint at this time.
1062     * @method clearConstraints
1063     */
1064    clearConstraints: function() {
1065        this.constrainX = false;
1066        this.constrainY = false;
1067        this.clearTicks();
1068    },
1069
1070    /**
1071     * Clears any tick interval defined for this instance
1072     * @method clearTicks
1073     */
1074    clearTicks: function() {
1075        this.xTicks = null;
1076        this.yTicks = null;
1077        this.xTickSize = 0;
1078        this.yTickSize = 0;
1079    },
1080
1081    /**
1082     * By default, the element can be dragged any place on the screen.  Set
1083     * this to limit the vertical travel of the element.  Pass in 0,0 for the
1084     * parameters if you want to lock the drag to the x axis.
1085     * @method setYConstraint
1086     * @param {int} iUp the number of pixels the element can move up
1087     * @param {int} iDown the number of pixels the element can move down
1088     * @param {int} iTickSize optional parameter for specifying that the
1089     * element should move iTickSize pixels at a time.
1090     */
1091    setYConstraint: function(iUp, iDown, iTickSize) {
1092        this.topConstraint = iUp;
1093        this.bottomConstraint = iDown;
1094
1095        this.minY = this.initPageY - iUp;
1096        this.maxY = this.initPageY + iDown;
1097        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
1098
1099        this.constrainY = true;
1100
1101    },
1102
1103    /**
1104     * resetConstraints must be called if you manually reposition a dd element.
1105     * @method resetConstraints
1106     * @param {boolean} maintainOffset
1107     */
1108    resetConstraints: function() {
1109        // Maintain offsets if necessary
1110        if (this.initPageX || this.initPageX === 0) {
1111            // figure out how much this thing has moved
1112            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
1113            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
1114
1115            this.setInitPosition(dx, dy);
1116
1117        // This is the first time we have detected the element's position
1118        } else {
1119            this.setInitPosition();
1120        }
1121
1122        if (this.constrainX) {
1123            this.setXConstraint( this.leftConstraint,
1124                                 this.rightConstraint,
1125                                 this.xTickSize        );
1126        }
1127
1128        if (this.constrainY) {
1129            this.setYConstraint( this.topConstraint,
1130                                 this.bottomConstraint,
1131                                 this.yTickSize         );
1132        }
1133    },
1134
1135    /**
1136     * Normally the drag element is moved pixel by pixel, but we can specify
1137     * that it move a number of pixels at a time.  This method resolves the
1138     * location when we have it set up like this.
1139     * @method getTick
1140     * @param {int} val where we want to place the object
1141     * @param {int[]} tickArray sorted array of valid points
1142     * @return {int} the closest tick
1143     * @private
1144     */
1145    getTick: function(val, tickArray) {
1146        if (!tickArray) {
1147            // If tick interval is not defined, it is effectively 1 pixel,
1148            // so we return the value passed to us.
1149            return val;
1150        } else if (tickArray[0] >= val) {
1151            // The value is lower than the first tick, so we return the first
1152            // tick.
1153            return tickArray[0];
1154        } else {
1155            for (var i=0, len=tickArray.length; i<len; ++i) {
1156                var next = i + 1;
1157                if (tickArray[next] && tickArray[next] >= val) {
1158                    var diff1 = val - tickArray[i];
1159                    var diff2 = tickArray[next] - val;
1160                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
1161                }
1162            }
1163
1164            // The value is larger than the last tick, so we return the last
1165            // tick.
1166            return tickArray[tickArray.length - 1];
1167        }
1168    },
1169
1170    /**
1171     * toString method
1172     * @method toString
1173     * @return {string} string representation of the dd obj
1174     */
1175    toString: function() {
1176        return ("DragDrop " + this.id);
1177    }
1178
1179};
1180
1181})();
1182/*
1183 * The drag and drop utility provides a framework for building drag and drop
1184 * applications.  In addition to enabling drag and drop for specific elements,
1185 * the drag and drop elements are tracked by the manager class, and the
1186 * interactions between the various elements are tracked during the drag and
1187 * the implementing code is notified about these important moments.
1188 */
1189
1190// Only load the library once.  Rewriting the manager class would orphan
1191// existing drag and drop instances.
1192if (!Ext.dd.DragDropMgr) {
1193
1194/**
1195 * @class Ext.dd.DragDropMgr
1196 * DragDropMgr is a singleton that tracks the element interaction for
1197 * all DragDrop items in the window.  Generally, you will not call
1198 * this class directly, but it does have helper methods that could
1199 * be useful in your DragDrop implementations.
1200 * @singleton
1201 */
1202Ext.dd.DragDropMgr = function() {
1203
1204    var Event = Ext.EventManager;
1205
1206    return {
1207
1208        /**
1209         * Two dimensional Array of registered DragDrop objects.  The first
1210         * dimension is the DragDrop item group, the second the DragDrop
1211         * object.
1212         * @property ids
1213         * @type String[]
1214         * @private
1215         * @static
1216         */
1217        ids: {},
1218
1219        /**
1220         * Array of element ids defined as drag handles.  Used to determine
1221         * if the element that generated the mousedown event is actually the
1222         * handle and not the html element itself.
1223         * @property handleIds
1224         * @type String[]
1225         * @private
1226         * @static
1227         */
1228        handleIds: {},
1229
1230        /**
1231         * the DragDrop object that is currently being dragged
1232         * @property dragCurrent
1233         * @type DragDrop
1234         * @private
1235         * @static
1236         **/
1237        dragCurrent: null,
1238
1239        /**
1240         * the DragDrop object(s) that are being hovered over
1241         * @property dragOvers
1242         * @type Array
1243         * @private
1244         * @static
1245         */
1246        dragOvers: {},
1247
1248        /**
1249         * the X distance between the cursor and the object being dragged
1250         * @property deltaX
1251         * @type int
1252         * @private
1253         * @static
1254         */
1255        deltaX: 0,
1256
1257        /**
1258         * the Y distance between the cursor and the object being dragged
1259         * @property deltaY
1260         * @type int
1261         * @private
1262         * @static
1263         */
1264        deltaY: 0,
1265
1266        /**
1267         * Flag to determine if we should prevent the default behavior of the
1268         * events we define. By default this is true, but this can be set to
1269         * false if you need the default behavior (not recommended)
1270         * @property preventDefault
1271         * @type boolean
1272         * @static
1273         */
1274        preventDefault: true,
1275
1276        /**
1277         * Flag to determine if we should stop the propagation of the events
1278         * we generate. This is true by default but you may want to set it to
1279         * false if the html element contains other features that require the
1280         * mouse click.
1281         * @property stopPropagation
1282         * @type boolean
1283         * @static
1284         */
1285        stopPropagation: true,
1286
1287        /**
1288         * Internal flag that is set to true when drag and drop has been
1289         * intialized
1290         * @property initialized
1291         * @private
1292         * @static
1293         */
1294        initialized: false,
1295
1296        /**
1297         * All drag and drop can be disabled.
1298         * @property locked
1299         * @private
1300         * @static
1301         */
1302        locked: false,
1303
1304        /**
1305         * Called the first time an element is registered.
1306         * @method init
1307         * @private
1308         * @static
1309         */
1310        init: function() {
1311            this.initialized = true;
1312        },
1313
1314        /**
1315         * In point mode, drag and drop interaction is defined by the
1316         * location of the cursor during the drag/drop
1317         * @property POINT
1318         * @type int
1319         * @static
1320         */
1321        POINT: 0,
1322
1323        /**
1324         * In intersect mode, drag and drop interaction is defined by the
1325         * overlap of two or more drag and drop objects.
1326         * @property INTERSECT
1327         * @type int
1328         * @static
1329         */
1330        INTERSECT: 1,
1331
1332        /**
1333         * The current drag and drop mode.  Default: POINT
1334         * @property mode
1335         * @type int
1336         * @static
1337         */
1338        mode: 0,
1339
1340        /**
1341         * Runs method on all drag and drop objects
1342         * @method _execOnAll
1343         * @private
1344         * @static
1345         */
1346        _execOnAll: function(sMethod, args) {
1347            for (var i in this.ids) {
1348                for (var j in this.ids[i]) {
1349                    var oDD = this.ids[i][j];
1350                    if (! this.isTypeOfDD(oDD)) {
1351                        continue;
1352                    }
1353                    oDD[sMethod].apply(oDD, args);
1354                }
1355            }
1356        },
1357
1358        /**
1359         * Drag and drop initialization.  Sets up the global event handlers
1360         * @method _onLoad
1361         * @private
1362         * @static
1363         */
1364        _onLoad: function() {
1365
1366            this.init();
1367
1368
1369            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
1370            Event.on(document, "mousemove", this.handleMouseMove, this, true);
1371            Event.on(window,   "unload",    this._onUnload, this, true);
1372            Event.on(window,   "resize",    this._onResize, this, true);
1373            // Event.on(window,   "mouseout",    this._test);
1374
1375        },
1376
1377        /**
1378         * Reset constraints on all drag and drop objs
1379         * @method _onResize
1380         * @private
1381         * @static
1382         */
1383        _onResize: function(e) {
1384            this._execOnAll("resetConstraints", []);
1385        },
1386
1387        /**
1388         * Lock all drag and drop functionality
1389         * @method lock
1390         * @static
1391         */
1392        lock: function() { this.locked = true; },
1393
1394        /**
1395         * Unlock all drag and drop functionality
1396         * @method unlock
1397         * @static
1398         */
1399        unlock: function() { this.locked = false; },
1400
1401        /**
1402         * Is drag and drop locked?
1403         * @method isLocked
1404         * @return {boolean} True if drag and drop is locked, false otherwise.
1405         * @static
1406         */
1407        isLocked: function() { return this.locked; },
1408
1409        /**
1410         * Location cache that is set for all drag drop objects when a drag is
1411         * initiated, cleared when the drag is finished.
1412         * @property locationCache
1413         * @private
1414         * @static
1415         */
1416        locationCache: {},
1417
1418        /**
1419         * Set useCache to false if you want to force object the lookup of each
1420         * drag and drop linked element constantly during a drag.
1421         * @property useCache
1422         * @type boolean
1423         * @static
1424         */
1425        useCache: true,
1426
1427        /**
1428         * The number of pixels that the mouse needs to move after the
1429         * mousedown before the drag is initiated.  Default=3;
1430         * @property clickPixelThresh
1431         * @type int
1432         * @static
1433         */
1434        clickPixelThresh: 3,
1435
1436        /**
1437         * The number of milliseconds after the mousedown event to initiate the
1438         * drag if we don't get a mouseup event. Default=350
1439         * @property clickTimeThresh
1440         * @type int
1441         * @static
1442         */
1443        clickTimeThresh: 350,
1444
1445        /**
1446         * Flag that indicates that either the drag pixel threshold or the
1447         * mousdown time threshold has been met
1448         * @property dragThreshMet
1449         * @type boolean
1450         * @private
1451         * @static
1452         */
1453        dragThreshMet: false,
1454
1455        /**
1456         * Timeout used for the click time threshold
1457         * @property clickTimeout
1458         * @type Object
1459         * @private
1460         * @static
1461         */
1462        clickTimeout: null,
1463
1464        /**
1465         * The X position of the mousedown event stored for later use when a
1466         * drag threshold is met.
1467         * @property startX
1468         * @type int
1469         * @private
1470         * @static
1471         */
1472        startX: 0,
1473
1474        /**
1475         * The Y position of the mousedown event stored for later use when a
1476         * drag threshold is met.
1477         * @property startY
1478         * @type int
1479         * @private
1480         * @static
1481         */
1482        startY: 0,
1483
1484        /**
1485         * Each DragDrop instance must be registered with the DragDropMgr.
1486         * This is executed in DragDrop.init()
1487         * @method regDragDrop
1488         * @param {DragDrop} oDD the DragDrop object to register
1489         * @param {String} sGroup the name of the group this element belongs to
1490         * @static
1491         */
1492        regDragDrop: function(oDD, sGroup) {
1493            if (!this.initialized) { this.init(); }
1494
1495            if (!this.ids[sGroup]) {
1496                this.ids[sGroup] = {};
1497            }
1498            this.ids[sGroup][oDD.id] = oDD;
1499        },
1500
1501        /**
1502         * Removes the supplied dd instance from the supplied group. Executed
1503         * by DragDrop.removeFromGroup, so don't call this function directly.
1504         * @method removeDDFromGroup
1505         * @private
1506         * @static
1507         */
1508        removeDDFromGroup: function(oDD, sGroup) {
1509            if (!this.ids[sGroup]) {
1510                this.ids[sGroup] = {};
1511            }
1512
1513            var obj = this.ids[sGroup];
1514            if (obj && obj[oDD.id]) {
1515                delete obj[oDD.id];
1516            }
1517        },
1518
1519        /**
1520         * Unregisters a drag and drop item.  This is executed in
1521         * DragDrop.unreg, use that method instead of calling this directly.
1522         * @method _remove
1523         * @private
1524         * @static
1525         */
1526        _remove: function(oDD) {
1527            for (var g in oDD.groups) {
1528                if (g && this.ids[g] && this.ids[g][oDD.id]) {
1529                    delete this.ids[g][oDD.id];
1530                }
1531            }
1532            delete this.handleIds[oDD.id];
1533        },
1534
1535        /**
1536         * Each DragDrop handle element must be registered.  This is done
1537         * automatically when executing DragDrop.setHandleElId()
1538         * @method regHandle
1539         * @param {String} sDDId the DragDrop id this element is a handle for
1540         * @param {String} sHandleId the id of the element that is the drag
1541         * handle
1542         * @static
1543         */
1544        regHandle: function(sDDId, sHandleId) {
1545            if (!this.handleIds[sDDId]) {
1546                this.handleIds[sDDId] = {};
1547            }
1548            this.handleIds[sDDId][sHandleId] = sHandleId;
1549        },
1550
1551        /**
1552         * Utility function to determine if a given element has been
1553         * registered as a drag drop item.
1554         * @method isDragDrop
1555         * @param {String} id the element id to check
1556         * @return {boolean} true if this element is a DragDrop item,
1557         * false otherwise
1558         * @static
1559         */
1560        isDragDrop: function(id) {
1561            return ( this.getDDById(id) ) ? true : false;
1562        },
1563
1564        /**
1565         * Returns the drag and drop instances that are in all groups the
1566         * passed in instance belongs to.
1567         * @method getRelated
1568         * @param {DragDrop} p_oDD the obj to get related data for
1569         * @param {boolean} bTargetsOnly if true, only return targetable objs
1570         * @return {DragDrop[]} the related instances
1571         * @static
1572         */
1573        getRelated: function(p_oDD, bTargetsOnly) {
1574            var oDDs = [];
1575            for (var i in p_oDD.groups) {
1576                for (var j in this.ids[i]) {
1577                    var dd = this.ids[i][j];
1578                    if (! this.isTypeOfDD(dd)) {
1579                        continue;
1580                    }
1581                    if (!bTargetsOnly || dd.isTarget) {
1582                        oDDs[oDDs.length] = dd;
1583                    }
1584                }
1585            }
1586
1587            return oDDs;
1588        },
1589
1590        /**
1591         * Returns true if the specified dd target is a legal target for
1592         * the specifice drag obj
1593         * @method isLegalTarget
1594         * @param {DragDrop} oDD the drag obj
1595         * @param {DragDrop} oTargetDD the target
1596         * @return {boolean} true if the target is a legal target for the
1597         * dd obj
1598         * @static
1599         */
1600        isLegalTarget: function (oDD, oTargetDD) {
1601            var targets = this.getRelated(oDD, true);
1602            for (var i=0, len=targets.length;i<len;++i) {
1603                if (targets[i].id == oTargetDD.id) {
1604                    return true;
1605                }
1606            }
1607
1608            return false;
1609        },
1610
1611        /**
1612         * My goal is to be able to transparently determine if an object is
1613         * typeof DragDrop, and the exact subclass of DragDrop.  typeof
1614         * returns "object", oDD.constructor.toString() always returns
1615         * "DragDrop" and not the name of the subclass.  So for now it just
1616         * evaluates a well-known variable in DragDrop.
1617         * @method isTypeOfDD
1618         * @param {Object} the object to evaluate
1619         * @return {boolean} true if typeof oDD = DragDrop
1620         * @static
1621         */
1622        isTypeOfDD: function (oDD) {
1623            return (oDD && oDD.__ygDragDrop);
1624        },
1625
1626        /**
1627         * Utility function to determine if a given element has been
1628         * registered as a drag drop handle for the given Drag Drop object.
1629         * @method isHandle
1630         * @param {String} id the element id to check
1631         * @return {boolean} 

Large files files are truncated, but you can click here to view the full file