[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-dragdrop/ -> yui2-dragdrop-debug.js (source)

   1  YUI.add('yui2-dragdrop', function(Y) {
   2      var YAHOO    = Y.YUI2;
   3      /*
   4  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
   5  Code licensed under the BSD License:
   6  http://developer.yahoo.com/yui/license.html
   7  version: 2.9.0
   8  */
   9  /**
  10   * The drag and drop utility provides a framework for building drag and drop
  11   * applications.  In addition to enabling drag and drop for specific elements,
  12   * the drag and drop elements are tracked by the manager class, and the
  13   * interactions between the various elements are tracked during the drag and
  14   * the implementing code is notified about these important moments.
  15   * @module dragdrop
  16   * @title Drag and Drop
  17   * @requires yahoo,dom,event
  18   * @namespace YAHOO.util
  19   */
  20  
  21  // Only load the library once.  Rewriting the manager class would orphan 
  22  // existing drag and drop instances.
  23  if (!YAHOO.util.DragDropMgr) {
  24  
  25  /**
  26   * DragDropMgr is a singleton that tracks the element interaction for 
  27   * all DragDrop items in the window.  Generally, you will not call 
  28   * this class directly, but it does have helper methods that could 
  29   * be useful in your DragDrop implementations.
  30   * @class DragDropMgr
  31   * @static
  32   */
  33  YAHOO.util.DragDropMgr = function() {
  34  
  35      var Event = YAHOO.util.Event,
  36          Dom = YAHOO.util.Dom;
  37  
  38      return {
  39          /**
  40          * This property is used to turn on global use of the shim element on all DragDrop instances, defaults to false for backcompat. (Use: YAHOO.util.DDM.useShim = true)
  41          * @property useShim
  42          * @type Boolean
  43          * @static
  44          */
  45          useShim: false,
  46          /**
  47          * This property is used to determine if the shim is active over the screen, default false.
  48          * @private
  49          * @property _shimActive
  50          * @type Boolean
  51          * @static
  52          */
  53          _shimActive: false,
  54          /**
  55          * This property is used when useShim is set on a DragDrop object to store the current state of DDM.useShim so it can be reset when a drag operation is done.
  56          * @private
  57          * @property _shimState
  58          * @type Boolean
  59          * @static
  60          */
  61          _shimState: false,
  62          /**
  63          * This property is used when useShim is set to true, it will set the opacity on the shim to .5 for debugging. Use: (YAHOO.util.DDM._debugShim = true;)
  64          * @private
  65          * @property _debugShim
  66          * @type Boolean
  67          * @static
  68          */
  69          _debugShim: false,
  70          /**
  71          * This method will create a shim element (giving it the id of yui-ddm-shim), it also attaches the mousemove and mouseup listeners to it and attaches a scroll listener on the window
  72          * @private
  73          * @method _sizeShim
  74          * @static
  75          */
  76          _createShim: function() {
  77              YAHOO.log('Creating Shim Element', 'info', 'DragDropMgr');
  78              var s = document.createElement('div');
  79              s.id = 'yui-ddm-shim';
  80              if (document.body.firstChild) {
  81                  document.body.insertBefore(s, document.body.firstChild);
  82              } else {
  83                  document.body.appendChild(s);
  84              }
  85              s.style.display = 'none';
  86              s.style.backgroundColor = 'red';
  87              s.style.position = 'absolute';
  88              s.style.zIndex = '99999';
  89              Dom.setStyle(s, 'opacity', '0');
  90              this._shim = s;
  91              Event.on(s, "mouseup",   this.handleMouseUp, this, true);
  92              Event.on(s, "mousemove", this.handleMouseMove, this, true);
  93              Event.on(window, 'scroll', this._sizeShim, this, true);
  94          },
  95          /**
  96          * This method will size the shim, called from activate and on window scroll event
  97          * @private
  98          * @method _sizeShim
  99          * @static
 100          */
 101          _sizeShim: function() {
 102              if (this._shimActive) {
 103                  YAHOO.log('Sizing Shim', 'info', 'DragDropMgr');
 104                  var s = this._shim;
 105                  s.style.height = Dom.getDocumentHeight() + 'px';
 106                  s.style.width = Dom.getDocumentWidth() + 'px';
 107                  s.style.top = '0';
 108                  s.style.left = '0';
 109              }
 110          },
 111          /**
 112          * This method will create the shim element if needed, then show the shim element, size the element and set the _shimActive property to true
 113          * @private
 114          * @method _activateShim
 115          * @static
 116          */
 117          _activateShim: function() {
 118              if (this.useShim) {
 119                  YAHOO.log('Activating Shim', 'info', 'DragDropMgr');
 120                  if (!this._shim) {
 121                      this._createShim();
 122                  }
 123                  this._shimActive = true;
 124                  var s = this._shim,
 125                      o = '0';
 126                  if (this._debugShim) {
 127                      o = '.5';
 128                  }
 129                  Dom.setStyle(s, 'opacity', o);
 130                  this._sizeShim();
 131                  s.style.display = 'block';
 132              }
 133          },
 134          /**
 135          * This method will hide the shim element and set the _shimActive property to false
 136          * @private
 137          * @method _deactivateShim
 138          * @static
 139          */
 140          _deactivateShim: function() {
 141              YAHOO.log('Deactivating Shim', 'info', 'DragDropMgr');
 142              this._shim.style.display = 'none';
 143              this._shimActive = false;
 144          },
 145          /**
 146          * The HTML element created to use as a shim over the document to track mouse movements
 147          * @private
 148          * @property _shim
 149          * @type HTMLElement
 150          * @static
 151          */
 152          _shim: null,
 153          /**
 154           * Two dimensional Array of registered DragDrop objects.  The first 
 155           * dimension is the DragDrop item group, the second the DragDrop 
 156           * object.
 157           * @property ids
 158           * @type {string: string}
 159           * @private
 160           * @static
 161           */
 162          ids: {},
 163  
 164          /**
 165           * Array of element ids defined as drag handles.  Used to determine 
 166           * if the element that generated the mousedown event is actually the 
 167           * handle and not the html element itself.
 168           * @property handleIds
 169           * @type {string: string}
 170           * @private
 171           * @static
 172           */
 173          handleIds: {},
 174  
 175          /**
 176           * the DragDrop object that is currently being dragged
 177           * @property dragCurrent
 178           * @type DragDrop
 179           * @private
 180           * @static
 181           **/
 182          dragCurrent: null,
 183  
 184          /**
 185           * the DragDrop object(s) that are being hovered over
 186           * @property dragOvers
 187           * @type Array
 188           * @private
 189           * @static
 190           */
 191          dragOvers: {},
 192  
 193          /**
 194           * the X distance between the cursor and the object being dragged
 195           * @property deltaX
 196           * @type int
 197           * @private
 198           * @static
 199           */
 200          deltaX: 0,
 201  
 202          /**
 203           * the Y distance between the cursor and the object being dragged
 204           * @property deltaY
 205           * @type int
 206           * @private
 207           * @static
 208           */
 209          deltaY: 0,
 210  
 211          /**
 212           * Flag to determine if we should prevent the default behavior of the
 213           * events we define. By default this is true, but this can be set to 
 214           * false if you need the default behavior (not recommended)
 215           * @property preventDefault
 216           * @type boolean
 217           * @static
 218           */
 219          preventDefault: true,
 220  
 221          /**
 222           * Flag to determine if we should stop the propagation of the events 
 223           * we generate. This is true by default but you may want to set it to
 224           * false if the html element contains other features that require the
 225           * mouse click.
 226           * @property stopPropagation
 227           * @type boolean
 228           * @static
 229           */
 230          stopPropagation: true,
 231  
 232          /**
 233           * Internal flag that is set to true when drag and drop has been
 234           * initialized
 235           * @property initialized
 236           * @private
 237           * @static
 238           */
 239          initialized: false,
 240  
 241          /**
 242           * All drag and drop can be disabled.
 243           * @property locked
 244           * @private
 245           * @static
 246           */
 247          locked: false,
 248  
 249          /**
 250           * Provides additional information about the the current set of
 251           * interactions.  Can be accessed from the event handlers. It
 252           * contains the following properties:
 253           *
 254           *       out:       onDragOut interactions
 255           *       enter:     onDragEnter interactions
 256           *       over:      onDragOver interactions
 257           *       drop:      onDragDrop interactions
 258           *       point:     The location of the cursor
 259           *       draggedRegion: The location of dragged element at the time
 260           *                      of the interaction
 261           *       sourceRegion: The location of the source elemtn at the time
 262           *                     of the interaction
 263           *       validDrop: boolean
 264           * @property interactionInfo
 265           * @type object
 266           * @static
 267           */
 268          interactionInfo: null,
 269  
 270          /**
 271           * Called the first time an element is registered.
 272           * @method init
 273           * @private
 274           * @static
 275           */
 276          init: function() {
 277              this.initialized = true;
 278          },
 279  
 280          /**
 281           * In point mode, drag and drop interaction is defined by the 
 282           * location of the cursor during the drag/drop
 283           * @property POINT
 284           * @type int
 285           * @static
 286           * @final
 287           */
 288          POINT: 0,
 289  
 290          /**
 291           * In intersect mode, drag and drop interaction is defined by the 
 292           * cursor position or the amount of overlap of two or more drag and 
 293           * drop objects.
 294           * @property INTERSECT
 295           * @type int
 296           * @static
 297           * @final
 298           */
 299          INTERSECT: 1,
 300  
 301          /**
 302           * In intersect mode, drag and drop interaction is defined only by the 
 303           * overlap of two or more drag and drop objects.
 304           * @property STRICT_INTERSECT
 305           * @type int
 306           * @static
 307           * @final
 308           */
 309          STRICT_INTERSECT: 2,
 310  
 311          /**
 312           * The current drag and drop mode.  Default: POINT
 313           * @property mode
 314           * @type int
 315           * @static
 316           */
 317          mode: 0,
 318  
 319          /**
 320           * Runs method on all drag and drop objects
 321           * @method _execOnAll
 322           * @private
 323           * @static
 324           */
 325          _execOnAll: function(sMethod, args) {
 326              for (var i in this.ids) {
 327                  for (var j in this.ids[i]) {
 328                      var oDD = this.ids[i][j];
 329                      if (! this.isTypeOfDD(oDD)) {
 330                          continue;
 331                      }
 332                      oDD[sMethod].apply(oDD, args);
 333                  }
 334              }
 335          },
 336  
 337          /**
 338           * Drag and drop initialization.  Sets up the global event handlers
 339           * @method _onLoad
 340           * @private
 341           * @static
 342           */
 343          _onLoad: function() {
 344  
 345              this.init();
 346  
 347              YAHOO.log("DragDropMgr onload", "info", "DragDropMgr");
 348              Event.on(document, "mouseup",   this.handleMouseUp, this, true);
 349              Event.on(document, "mousemove", this.handleMouseMove, this, true);
 350              Event.on(window,   "unload",    this._onUnload, this, true);
 351              Event.on(window,   "resize",    this._onResize, this, true);
 352              // Event.on(window,   "mouseout",    this._test);
 353  
 354          },
 355  
 356          /**
 357           * Reset constraints on all drag and drop objs
 358           * @method _onResize
 359           * @private
 360           * @static
 361           */
 362          _onResize: function(e) {
 363              YAHOO.log("window resize", "info", "DragDropMgr");
 364              this._execOnAll("resetConstraints", []);
 365          },
 366  
 367          /**
 368           * Lock all drag and drop functionality
 369           * @method lock
 370           * @static
 371           */
 372          lock: function() { this.locked = true; },
 373  
 374          /**
 375           * Unlock all drag and drop functionality
 376           * @method unlock
 377           * @static
 378           */
 379          unlock: function() { this.locked = false; },
 380  
 381          /**
 382           * Is drag and drop locked?
 383           * @method isLocked
 384           * @return {boolean} True if drag and drop is locked, false otherwise.
 385           * @static
 386           */
 387          isLocked: function() { return this.locked; },
 388  
 389          /**
 390           * Location cache that is set for all drag drop objects when a drag is
 391           * initiated, cleared when the drag is finished.
 392           * @property locationCache
 393           * @private
 394           * @static
 395           */
 396          locationCache: {},
 397  
 398          /**
 399           * Set useCache to false if you want to force object the lookup of each
 400           * drag and drop linked element constantly during a drag.
 401           * @property useCache
 402           * @type boolean
 403           * @static
 404           */
 405          useCache: true,
 406  
 407          /**
 408           * The number of pixels that the mouse needs to move after the 
 409           * mousedown before the drag is initiated.  Default=3;
 410           * @property clickPixelThresh
 411           * @type int
 412           * @static
 413           */
 414          clickPixelThresh: 3,
 415  
 416          /**
 417           * The number of milliseconds after the mousedown event to initiate the
 418           * drag if we don't get a mouseup event. Default=1000
 419           * @property clickTimeThresh
 420           * @type int
 421           * @static
 422           */
 423          clickTimeThresh: 1000,
 424  
 425          /**
 426           * Flag that indicates that either the drag pixel threshold or the 
 427           * mousdown time threshold has been met
 428           * @property dragThreshMet
 429           * @type boolean
 430           * @private
 431           * @static
 432           */
 433          dragThreshMet: false,
 434  
 435          /**
 436           * Timeout used for the click time threshold
 437           * @property clickTimeout
 438           * @type Object
 439           * @private
 440           * @static
 441           */
 442          clickTimeout: null,
 443  
 444          /**
 445           * The X position of the mousedown event stored for later use when a 
 446           * drag threshold is met.
 447           * @property startX
 448           * @type int
 449           * @private
 450           * @static
 451           */
 452          startX: 0,
 453  
 454          /**
 455           * The Y position of the mousedown event stored for later use when a 
 456           * drag threshold is met.
 457           * @property startY
 458           * @type int
 459           * @private
 460           * @static
 461           */
 462          startY: 0,
 463  
 464          /**
 465           * Flag to determine if the drag event was fired from the click timeout and
 466           * not the mouse move threshold.
 467           * @property fromTimeout
 468           * @type boolean
 469           * @private
 470           * @static
 471           */
 472          fromTimeout: false,
 473  
 474          /**
 475           * Each DragDrop instance must be registered with the DragDropMgr.  
 476           * This is executed in DragDrop.init()
 477           * @method regDragDrop
 478           * @param {DragDrop} oDD the DragDrop object to register
 479           * @param {String} sGroup the name of the group this element belongs to
 480           * @static
 481           */
 482          regDragDrop: function(oDD, sGroup) {
 483              if (!this.initialized) { this.init(); }
 484              
 485              if (!this.ids[sGroup]) {
 486                  this.ids[sGroup] = {};
 487              }
 488              this.ids[sGroup][oDD.id] = oDD;
 489          },
 490  
 491          /**
 492           * Removes the supplied dd instance from the supplied group. Executed
 493           * by DragDrop.removeFromGroup, so don't call this function directly.
 494           * @method removeDDFromGroup
 495           * @private
 496           * @static
 497           */
 498          removeDDFromGroup: function(oDD, sGroup) {
 499              if (!this.ids[sGroup]) {
 500                  this.ids[sGroup] = {};
 501              }
 502  
 503              var obj = this.ids[sGroup];
 504              if (obj && obj[oDD.id]) {
 505                  delete obj[oDD.id];
 506              }
 507          },
 508  
 509          /**
 510           * Unregisters a drag and drop item.  This is executed in 
 511           * DragDrop.unreg, use that method instead of calling this directly.
 512           * @method _remove
 513           * @private
 514           * @static
 515           */
 516          _remove: function(oDD) {
 517              for (var g in oDD.groups) {
 518                  if (g) {
 519                      var item = this.ids[g];
 520                      if (item && item[oDD.id]) {
 521                          delete item[oDD.id];
 522                      }
 523                  }
 524                  
 525              }
 526              delete this.handleIds[oDD.id];
 527          },
 528  
 529          /**
 530           * Each DragDrop handle element must be registered.  This is done
 531           * automatically when executing DragDrop.setHandleElId()
 532           * @method regHandle
 533           * @param {String} sDDId the DragDrop id this element is a handle for
 534           * @param {String} sHandleId the id of the element that is the drag 
 535           * handle
 536           * @static
 537           */
 538          regHandle: function(sDDId, sHandleId) {
 539              if (!this.handleIds[sDDId]) {
 540                  this.handleIds[sDDId] = {};
 541              }
 542              this.handleIds[sDDId][sHandleId] = sHandleId;
 543          },
 544  
 545          /**
 546           * Utility function to determine if a given element has been 
 547           * registered as a drag drop item.
 548           * @method isDragDrop
 549           * @param {String} id the element id to check
 550           * @return {boolean} true if this element is a DragDrop item, 
 551           * false otherwise
 552           * @static
 553           */
 554          isDragDrop: function(id) {
 555              return ( this.getDDById(id) ) ? true : false;
 556          },
 557  
 558          /**
 559           * Returns the drag and drop instances that are in all groups the
 560           * passed in instance belongs to.
 561           * @method getRelated
 562           * @param {DragDrop} p_oDD the obj to get related data for
 563           * @param {boolean} bTargetsOnly if true, only return targetable objs
 564           * @return {DragDrop[]} the related instances
 565           * @static
 566           */
 567          getRelated: function(p_oDD, bTargetsOnly) {
 568              var oDDs = [];
 569              for (var i in p_oDD.groups) {
 570                  for (var j in this.ids[i]) {
 571                      var dd = this.ids[i][j];
 572                      if (! this.isTypeOfDD(dd)) {
 573                          continue;
 574                      }
 575                      if (!bTargetsOnly || dd.isTarget) {
 576                          oDDs[oDDs.length] = dd;
 577                      }
 578                  }
 579              }
 580  
 581              return oDDs;
 582          },
 583  
 584          /**
 585           * Returns true if the specified dd target is a legal target for 
 586           * the specifice drag obj
 587           * @method isLegalTarget
 588           * @param {DragDrop} the drag obj
 589           * @param {DragDrop} the target
 590           * @return {boolean} true if the target is a legal target for the 
 591           * dd obj
 592           * @static
 593           */
 594          isLegalTarget: function (oDD, oTargetDD) {
 595              var targets = this.getRelated(oDD, true);
 596              for (var i=0, len=targets.length;i<len;++i) {
 597                  if (targets[i].id == oTargetDD.id) {
 598                      return true;
 599                  }
 600              }
 601  
 602              return false;
 603          },
 604  
 605          /**
 606           * My goal is to be able to transparently determine if an object is
 607           * typeof DragDrop, and the exact subclass of DragDrop.  typeof 
 608           * returns "object", oDD.constructor.toString() always returns
 609           * "DragDrop" and not the name of the subclass.  So for now it just
 610           * evaluates a well-known variable in DragDrop.
 611           * @method isTypeOfDD
 612           * @param {Object} the object to evaluate
 613           * @return {boolean} true if typeof oDD = DragDrop
 614           * @static
 615           */
 616          isTypeOfDD: function (oDD) {
 617              return (oDD && oDD.__ygDragDrop);
 618          },
 619  
 620          /**
 621           * Utility function to determine if a given element has been 
 622           * registered as a drag drop handle for the given Drag Drop object.
 623           * @method isHandle
 624           * @param {String} id the element id to check
 625           * @return {boolean} true if this element is a DragDrop handle, false 
 626           * otherwise
 627           * @static
 628           */
 629          isHandle: function(sDDId, sHandleId) {
 630              return ( this.handleIds[sDDId] && 
 631                              this.handleIds[sDDId][sHandleId] );
 632          },
 633  
 634          /**
 635           * Returns the DragDrop instance for a given id
 636           * @method getDDById
 637           * @param {String} id the id of the DragDrop object
 638           * @return {DragDrop} the drag drop object, null if it is not found
 639           * @static
 640           */
 641          getDDById: function(id) {
 642              for (var i in this.ids) {
 643                  if (this.ids[i][id]) {
 644                      return this.ids[i][id];
 645                  }
 646              }
 647              return null;
 648          },
 649  
 650          /**
 651           * Fired after a registered DragDrop object gets the mousedown event.
 652           * Sets up the events required to track the object being dragged
 653           * @method handleMouseDown
 654           * @param {Event} e the event
 655           * @param oDD the DragDrop object being dragged
 656           * @private
 657           * @static
 658           */
 659          handleMouseDown: function(e, oDD) {
 660              //this._activateShim();
 661  
 662              this.currentTarget = YAHOO.util.Event.getTarget(e);
 663  
 664              this.dragCurrent = oDD;
 665  
 666              var el = oDD.getEl();
 667  
 668              // track start position
 669              this.startX = YAHOO.util.Event.getPageX(e);
 670              this.startY = YAHOO.util.Event.getPageY(e);
 671  
 672              this.deltaX = this.startX - el.offsetLeft;
 673              this.deltaY = this.startY - el.offsetTop;
 674  
 675              this.dragThreshMet = false;
 676  
 677              this.clickTimeout = setTimeout( 
 678                      function() { 
 679                          var DDM = YAHOO.util.DDM;
 680                          DDM.startDrag(DDM.startX, DDM.startY);
 681                          DDM.fromTimeout = true;
 682                      }, 
 683                      this.clickTimeThresh );
 684          },
 685  
 686          /**
 687           * Fired when either the drag pixel threshold or the mousedown hold 
 688           * time threshold has been met.
 689           * @method startDrag
 690           * @param x {int} the X position of the original mousedown
 691           * @param y {int} the Y position of the original mousedown
 692           * @static
 693           */
 694          startDrag: function(x, y) {
 695              if (this.dragCurrent && this.dragCurrent.useShim) {
 696                  this._shimState = this.useShim;
 697                  this.useShim = true;
 698              }
 699              this._activateShim();
 700              YAHOO.log("firing drag start events", "info", "DragDropMgr");
 701              clearTimeout(this.clickTimeout);
 702              var dc = this.dragCurrent;
 703              if (dc && dc.events.b4StartDrag) {
 704                  dc.b4StartDrag(x, y);
 705                  dc.fireEvent('b4StartDragEvent', { x: x, y: y });
 706              }
 707              if (dc && dc.events.startDrag) {
 708                  dc.startDrag(x, y);
 709                  dc.fireEvent('startDragEvent', { x: x, y: y });
 710              }
 711              this.dragThreshMet = true;
 712          },
 713  
 714          /**
 715           * Internal function to handle the mouseup event.  Will be invoked 
 716           * from the context of the document.
 717           * @method handleMouseUp
 718           * @param {Event} e the event
 719           * @private
 720           * @static
 721           */
 722          handleMouseUp: function(e) {
 723              if (this.dragCurrent) {
 724                  clearTimeout(this.clickTimeout);
 725  
 726                  if (this.dragThreshMet) {
 727                      YAHOO.log("mouseup detected - completing drag", "info", "DragDropMgr");
 728                      if (this.fromTimeout) {
 729                          YAHOO.log('fromTimeout is true (mouse didn\'t move), call handleMouseMove so we can get the dragOver event', 'info', 'DragDropMgr');
 730                          this.fromTimeout = false;
 731                          this.handleMouseMove(e);
 732                      }
 733                      this.fromTimeout = false;
 734                      this.fireEvents(e, true);
 735                  } else {
 736                      YAHOO.log("drag threshold not met", "info", "DragDropMgr");
 737                  }
 738  
 739                  this.stopDrag(e);
 740  
 741                  this.stopEvent(e);
 742              }
 743          },
 744  
 745          /**
 746           * Utility to stop event propagation and event default, if these 
 747           * features are turned on.
 748           * @method stopEvent
 749           * @param {Event} e the event as returned by this.getEvent()
 750           * @static
 751           */
 752          stopEvent: function(e) {
 753              if (this.stopPropagation) {
 754                  YAHOO.util.Event.stopPropagation(e);
 755              }
 756  
 757              if (this.preventDefault) {
 758                  YAHOO.util.Event.preventDefault(e);
 759              }
 760          },
 761  
 762          /** 
 763           * Ends the current drag, cleans up the state, and fires the endDrag
 764           * and mouseUp events.  Called internally when a mouseup is detected
 765           * during the drag.  Can be fired manually during the drag by passing
 766           * either another event (such as the mousemove event received in onDrag)
 767           * or a fake event with pageX and pageY defined (so that endDrag and
 768           * onMouseUp have usable position data.).  Alternatively, pass true
 769           * for the silent parameter so that the endDrag and onMouseUp events
 770           * are skipped (so no event data is needed.)
 771           *
 772           * @method stopDrag
 773           * @param {Event} e the mouseup event, another event (or a fake event) 
 774           *                  with pageX and pageY defined, or nothing if the 
 775           *                  silent parameter is true
 776           * @param {boolean} silent skips the enddrag and mouseup events if true
 777           * @static
 778           */
 779          stopDrag: function(e, silent) {
 780              // YAHOO.log("mouseup - removing event handlers");
 781              var dc = this.dragCurrent;
 782              // Fire the drag end event for the item that was dragged
 783              if (dc && !silent) {
 784                  if (this.dragThreshMet) {
 785                      YAHOO.log("firing endDrag events", "info", "DragDropMgr");
 786                      if (dc.events.b4EndDrag) {
 787                          dc.b4EndDrag(e);
 788                          dc.fireEvent('b4EndDragEvent', { e: e });
 789                      }
 790                      if (dc.events.endDrag) {
 791                          dc.endDrag(e);
 792                          dc.fireEvent('endDragEvent', { e: e });
 793                      }
 794                  }
 795                  if (dc.events.mouseUp) {
 796                      YAHOO.log("firing dragdrop onMouseUp event", "info", "DragDropMgr");
 797                      dc.onMouseUp(e);
 798                      dc.fireEvent('mouseUpEvent', { e: e });
 799                  }
 800              }
 801  
 802              if (this._shimActive) {
 803                  this._deactivateShim();
 804                  if (this.dragCurrent && this.dragCurrent.useShim) {
 805                      this.useShim = this._shimState;
 806                      this._shimState = false;
 807                  }
 808              }
 809  
 810              this.dragCurrent = null;
 811              this.dragOvers = {};
 812          },
 813  
 814          /** 
 815           * Internal function to handle the mousemove event.  Will be invoked 
 816           * from the context of the html element.
 817           *
 818           * @TODO figure out what we can do about mouse events lost when the 
 819           * user drags objects beyond the window boundary.  Currently we can 
 820           * detect this in internet explorer by verifying that the mouse is 
 821           * down during the mousemove event.  Firefox doesn't give us the 
 822           * button state on the mousemove event.
 823           * @method handleMouseMove
 824           * @param {Event} e the event
 825           * @private
 826           * @static
 827           */
 828          handleMouseMove: function(e) {
 829              //YAHOO.log("handlemousemove");
 830  
 831              var dc = this.dragCurrent;
 832              if (dc) {
 833                  // YAHOO.log("no current drag obj");
 834  
 835                  // var button = e.which || e.button;
 836                  // YAHOO.log("which: " + e.which + ", button: "+ e.button);
 837  
 838                  // check for IE < 9 mouseup outside of page boundary
 839                  if (YAHOO.env.ua.ie && (YAHOO.env.ua.ie < 9) && !e.button) {
 840                      YAHOO.log("button failure", "info", "DragDropMgr");
 841                      this.stopEvent(e);
 842                      return this.handleMouseUp(e);
 843                  } else {
 844                      if (e.clientX < 0 || e.clientY < 0) {
 845                          //This will stop the element from leaving the viewport in FF, Opera & Safari
 846                          //Not turned on yet
 847                          //YAHOO.log("Either clientX or clientY is negative, stop the event.", "info", "DragDropMgr");
 848                          //this.stopEvent(e);
 849                          //return false;
 850                      }
 851                  }
 852  
 853                  if (!this.dragThreshMet) {
 854                      var diffX = Math.abs(this.startX - YAHOO.util.Event.getPageX(e));
 855                      var diffY = Math.abs(this.startY - YAHOO.util.Event.getPageY(e));
 856                      // YAHOO.log("diffX: " + diffX + "diffY: " + diffY);
 857                      if (diffX > this.clickPixelThresh || 
 858                                  diffY > this.clickPixelThresh) {
 859                          YAHOO.log("pixel threshold met", "info", "DragDropMgr");
 860                          this.startDrag(this.startX, this.startY);
 861                      }
 862                  }
 863  
 864                  if (this.dragThreshMet) {
 865                      if (dc && dc.events.b4Drag) {
 866                          dc.b4Drag(e);
 867                          dc.fireEvent('b4DragEvent', { e: e});
 868                      }
 869                      if (dc && dc.events.drag) {
 870                          dc.onDrag(e);
 871                          dc.fireEvent('dragEvent', { e: e});
 872                      }
 873                      if (dc) {
 874                          this.fireEvents(e, false);
 875                      }
 876                  }
 877  
 878                  this.stopEvent(e);
 879              }
 880          },
 881          
 882          /**
 883           * Iterates over all of the DragDrop elements to find ones we are 
 884           * hovering over or dropping on
 885           * @method fireEvents
 886           * @param {Event} e the event
 887           * @param {boolean} isDrop is this a drop op or a mouseover op?
 888           * @private
 889           * @static
 890           */
 891          fireEvents: function(e, isDrop) {
 892              var dc = this.dragCurrent;
 893  
 894              // If the user did the mouse up outside of the window, we could 
 895              // get here even though we have ended the drag.
 896              // If the config option dragOnly is true, bail out and don't fire the events
 897              if (!dc || dc.isLocked() || dc.dragOnly) {
 898                  return;
 899              }
 900  
 901              var x = YAHOO.util.Event.getPageX(e),
 902                  y = YAHOO.util.Event.getPageY(e),
 903                  pt = new YAHOO.util.Point(x,y),
 904                  pos = dc.getTargetCoord(pt.x, pt.y),
 905                  el = dc.getDragEl(),
 906                  events = ['out', 'over', 'drop', 'enter'],
 907                  curRegion = new YAHOO.util.Region( pos.y, 
 908                                                 pos.x + el.offsetWidth,
 909                                                 pos.y + el.offsetHeight, 
 910                                                 pos.x ),
 911              
 912                  oldOvers = [], // cache the previous dragOver array
 913                  inGroupsObj  = {},
 914                  b4Results = {},
 915                  inGroups  = [],
 916                  data = {
 917                      outEvts: [],
 918                      overEvts: [],
 919                      dropEvts: [],
 920                      enterEvts: []
 921                  };
 922  
 923  
 924              // Check to see if the object(s) we were hovering over is no longer 
 925              // being hovered over so we can fire the onDragOut event
 926              for (var i in this.dragOvers) {
 927  
 928                  var ddo = this.dragOvers[i];
 929  
 930                  if (! this.isTypeOfDD(ddo)) {
 931                      continue;
 932                  }
 933                  if (! this.isOverTarget(pt, ddo, this.mode, curRegion)) {
 934                      data.outEvts.push( ddo );
 935                  }
 936  
 937                  oldOvers[i] = true;
 938                  delete this.dragOvers[i];
 939              }
 940  
 941              for (var sGroup in dc.groups) {
 942                  // YAHOO.log("Processing group " + sGroup);
 943                  
 944                  if ("string" != typeof sGroup) {
 945                      continue;
 946                  }
 947  
 948                  for (i in this.ids[sGroup]) {
 949                      var oDD = this.ids[sGroup][i];
 950                      if (! this.isTypeOfDD(oDD)) {
 951                          continue;
 952                      }
 953  
 954                      if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
 955                          if (this.isOverTarget(pt, oDD, this.mode, curRegion)) {
 956                              inGroupsObj[sGroup] = true;
 957                              // look for drop interactions
 958                              if (isDrop) {
 959                                  data.dropEvts.push( oDD );
 960                              // look for drag enter and drag over interactions
 961                              } else {
 962  
 963                                  // initial drag over: dragEnter fires
 964                                  if (!oldOvers[oDD.id]) {
 965                                      data.enterEvts.push( oDD );
 966                                  // subsequent drag overs: dragOver fires
 967                                  } else {
 968                                      data.overEvts.push( oDD );
 969                                  }
 970  
 971                                  this.dragOvers[oDD.id] = oDD;
 972                              }
 973                          }
 974                      }
 975                  }
 976              }
 977  
 978              this.interactionInfo = {
 979                  out:       data.outEvts,
 980                  enter:     data.enterEvts,
 981                  over:      data.overEvts,
 982                  drop:      data.dropEvts,
 983                  point:     pt,
 984                  draggedRegion:    curRegion,
 985                  sourceRegion: this.locationCache[dc.id],
 986                  validDrop: isDrop
 987              };
 988  
 989              
 990              for (var inG in inGroupsObj) {
 991                  inGroups.push(inG);
 992              }
 993  
 994              // notify about a drop that did not find a target
 995              if (isDrop && !data.dropEvts.length) {
 996                  YAHOO.log(dc.id + " dropped, but not on a target", "info", "DragDropMgr");
 997                  this.interactionInfo.validDrop = false;
 998                  if (dc.events.invalidDrop) {
 999                      dc.onInvalidDrop(e);
1000                      dc.fireEvent('invalidDropEvent', { e: e });
1001                  }
1002              }
1003              for (i = 0; i < events.length; i++) {
1004                  var tmp = null;
1005                  if (data[events[i] + 'Evts']) {
1006                      tmp = data[events[i] + 'Evts'];
1007                  }
1008                  if (tmp && tmp.length) {
1009                      var type = events[i].charAt(0).toUpperCase() + events[i].substr(1),
1010                          ev = 'onDrag' + type,
1011                          b4 = 'b4Drag' + type,
1012                          cev = 'drag' + type + 'Event',
1013                          check = 'drag' + type;
1014                      if (this.mode) {
1015                          YAHOO.log(dc.id + ' ' + ev + ': ' + tmp, "info", "DragDropMgr");
1016                          if (dc.events[b4]) {
1017                              dc[b4](e, tmp, inGroups);
1018                              b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp, group: inGroups });
1019                              
1020                          }
1021                          if (dc.events[check] && (b4Results[ev] !== false)) {
1022                              dc[ev](e, tmp, inGroups);
1023                              dc.fireEvent(cev, { event: e, info: tmp, group: inGroups });
1024                          }
1025                      } else {
1026                          for (var b = 0, len = tmp.length; b < len; ++b) {
1027                              YAHOO.log(dc.id + ' ' + ev + ': ' + tmp[b].id, "info", "DragDropMgr");
1028                              if (dc.events[b4]) {
1029                                  dc[b4](e, tmp[b].id, inGroups[0]);
1030                                  b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp[b].id, group: inGroups[0] });
1031                              }
1032                              if (dc.events[check] && (b4Results[ev] !== false)) {
1033                                  dc[ev](e, tmp[b].id, inGroups[0]);
1034                                  dc.fireEvent(cev, { event: e, info: tmp[b].id, group: inGroups[0] });
1035                              }
1036                          }
1037                      }
1038                  }
1039              }
1040          },
1041  
1042          /**
1043           * Helper function for getting the best match from the list of drag 
1044           * and drop objects returned by the drag and drop events when we are 
1045           * in INTERSECT mode.  It returns either the first object that the 
1046           * cursor is over, or the object that has the greatest overlap with 
1047           * the dragged element.
1048           * @method getBestMatch
1049           * @param  {DragDrop[]} dds The array of drag and drop objects 
1050           * targeted
1051           * @return {DragDrop}       The best single match
1052           * @static
1053           */
1054          getBestMatch: function(dds) {
1055              var winner = null;
1056  
1057              var len = dds.length;
1058  
1059              if (len == 1) {
1060                  winner = dds[0];
1061              } else {
1062                  // Loop through the targeted items
1063                  for (var i=0; i<len; ++i) {
1064                      var dd = dds[i];
1065                      // If the cursor is over the object, it wins.  If the 
1066                      // cursor is over multiple matches, the first one we come
1067                      // to wins.
1068                      if (this.mode == this.INTERSECT && dd.cursorIsOver) {
1069                          winner = dd;
1070                          break;
1071                      // Otherwise the object with the most overlap wins
1072                      } else {
1073                          if (!winner || !winner.overlap || (dd.overlap &&
1074                              winner.overlap.getArea() < dd.overlap.getArea())) {
1075                              winner = dd;
1076                          }
1077                      }
1078                  }
1079              }
1080  
1081              return winner;
1082          },
1083  
1084          /**
1085           * Refreshes the cache of the top-left and bottom-right points of the 
1086           * drag and drop objects in the specified group(s).  This is in the
1087           * format that is stored in the drag and drop instance, so typical 
1088           * usage is:
1089           * <code>
1090           * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups);
1091           * </code>
1092           * Alternatively:
1093           * <code>
1094           * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true});
1095           * </code>
1096           * @TODO this really should be an indexed array.  Alternatively this
1097           * method could accept both.
1098           * @method refreshCache
1099           * @param {Object} groups an associative array of groups to refresh
1100           * @static
1101           */
1102          refreshCache: function(groups) {
1103              YAHOO.log("refreshing element location cache", "info", "DragDropMgr");
1104  
1105              // refresh everything if group array is not provided
1106              var g = groups || this.ids;
1107  
1108              for (var sGroup in g) {
1109                  if ("string" != typeof sGroup) {
1110                      continue;
1111                  }
1112                  for (var i in this.ids[sGroup]) {
1113                      var oDD = this.ids[sGroup][i];
1114  
1115                      if (this.isTypeOfDD(oDD)) {
1116                          var loc = this.getLocation(oDD);
1117                          if (loc) {
1118                              this.locationCache[oDD.id] = loc;
1119                          } else {
1120                              delete this.locationCache[oDD.id];
1121  YAHOO.log("Could not get the loc for " + oDD.id, "warn", "DragDropMgr");
1122                          }
1123                      }
1124                  }
1125              }
1126          },
1127  
1128          /**
1129           * This checks to make sure an element exists and is in the DOM.  The
1130           * main purpose is to handle cases where innerHTML is used to remove
1131           * drag and drop objects from the DOM.  IE provides an 'unspecified
1132           * error' when trying to access the offsetParent of such an element
1133           * @method verifyEl
1134           * @param {HTMLElement} el the element to check
1135           * @return {boolean} true if the element looks usable
1136           * @static
1137           */
1138          verifyEl: function(el) {
1139              try {
1140                  if (el) {
1141                      var parent = el.offsetParent;
1142                      if (parent) {
1143                          return true;
1144                      }
1145                  }
1146              } catch(e) {
1147                  YAHOO.log("detected problem with an element", "info", "DragDropMgr");
1148              }
1149  
1150              return false;
1151          },
1152          
1153          /**
1154           * Returns a Region object containing the drag and drop element's position
1155           * and size, including the padding configured for it
1156           * @method getLocation
1157           * @param {DragDrop} oDD the drag and drop object to get the 
1158           *                       location for
1159           * @return {YAHOO.util.Region} a Region object representing the total area
1160           *                             the element occupies, including any padding
1161           *                             the instance is configured for.
1162           * @static
1163           */
1164          getLocation: function(oDD) {
1165              if (! this.isTypeOfDD(oDD)) {
1166                  YAHOO.log(oDD + " is not a DD obj", "info", "DragDropMgr");
1167                  return null;
1168              }
1169  
1170              var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
1171  
1172              try {
1173                  pos= YAHOO.util.Dom.getXY(el);
1174              } catch (e) { }
1175  
1176              if (!pos) {
1177                  YAHOO.log("getXY failed", "info", "DragDropMgr");
1178                  return null;
1179              }
1180  
1181              x1 = pos[0];
1182              x2 = x1 + el.offsetWidth;
1183              y1 = pos[1];
1184              y2 = y1 + el.offsetHeight;
1185  
1186              t = y1 - oDD.padding[0];
1187              r = x2 + oDD.padding[1];
1188              b = y2 + oDD.padding[2];
1189              l = x1 - oDD.padding[3];
1190  
1191              return new YAHOO.util.Region( t, r, b, l );
1192          },
1193  
1194          /**
1195           * Checks the cursor location to see if it over the target
1196           * @method isOverTarget
1197           * @param {YAHOO.util.Point} pt The point to evaluate
1198           * @param {DragDrop} oTarget the DragDrop object we are inspecting
1199           * @param {boolean} intersect true if we are in intersect mode
1200           * @param {YAHOO.util.Region} pre-cached location of the dragged element
1201           * @return {boolean} true if the mouse is over the target
1202           * @private
1203           * @static
1204           */
1205          isOverTarget: function(pt, oTarget, intersect, curRegion) {
1206              // use cache if available
1207              var loc = this.locationCache[oTarget.id];
1208              if (!loc || !this.useCache) {
1209                  YAHOO.log("cache not populated", "info", "DragDropMgr");
1210                  loc = this.getLocation(oTarget);
1211                  this.locationCache[oTarget.id] = loc;
1212  
1213                  YAHOO.log("cache: " + loc, "info", "DragDropMgr");
1214              }
1215  
1216              if (!loc) {
1217                  YAHOO.log("could not get the location of the element", "info", "DragDropMgr");
1218                  return false;
1219              }
1220  
1221              //YAHOO.log("loc: " + loc + ", pt: " + pt);
1222              oTarget.cursorIsOver = loc.contains( pt );
1223  
1224              // DragDrop is using this as a sanity check for the initial mousedown
1225              // in this case we are done.  In POINT mode, if the drag obj has no
1226              // contraints, we are done. Otherwise we need to evaluate the 
1227              // region the target as occupies to determine if the dragged element
1228              // overlaps with it.
1229              
1230              var dc = this.dragCurrent;
1231              if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {
1232  
1233                  //if (oTarget.cursorIsOver) {
1234                      //YAHOO.log("over " + oTarget + ", " + loc + ", " + pt, "warn");
1235                  //}
1236                  return oTarget.cursorIsOver;
1237              }
1238  
1239              oTarget.overlap = null;
1240  
1241  
1242              // Get the current location of the drag element, this is the
1243              // location of the mouse event less the delta that represents
1244              // where the original mousedown happened on the element.  We
1245              // need to consider constraints and ticks as well.
1246  
1247              if (!curRegion) {
1248                  var pos = dc.getTargetCoord(pt.x, pt.y);
1249                  var el = dc.getDragEl();
1250                  curRegion = new YAHOO.util.Region( pos.y, 
1251                                                     pos.x + el.offsetWidth,
1252                                                     pos.y + el.offsetHeight, 
1253                                                     pos.x );
1254              }
1255  
1256              var overlap = curRegion.intersect(loc);
1257  
1258              if (overlap) {
1259                  oTarget.overlap = overlap;
1260                  return (intersect) ? true : oTarget.cursorIsOver;
1261              } else {
1262                  return false;
1263              }
1264          },
1265  
1266          /**
1267           * unload event handler
1268           * @method _onUnload
1269           * @private
1270           * @static
1271           */
1272          _onUnload: function(e, me) {
1273              this.unregAll();
1274          },
1275  
1276          /**
1277           * Cleans up the drag and drop events and objects.
1278           * @method unregAll
1279           * @private
1280           * @static
1281           */
1282          unregAll: function() {
1283              YAHOO.log("unregister all", "info", "DragDropMgr");
1284  
1285              if (this.dragCurrent) {
1286                  this.stopDrag();
1287                  this.dragCurrent = null;
1288              }
1289  
1290              this._execOnAll("unreg", []);
1291  
1292              //for (var i in this.elementCache) {
1293                  //delete this.elementCache[i];
1294              //}
1295              //this.elementCache = {};
1296  
1297              this.ids = {};
1298          },
1299  
1300          /**
1301           * A cache of DOM elements
1302           * @property elementCache
1303           * @private
1304           * @static
1305           * @deprecated elements are not cached now
1306           */
1307          elementCache: {},
1308          
1309          /**
1310           * Get the wrapper for the DOM element specified
1311           * @method getElWrapper
1312           * @param {String} id the id of the element to get
1313           * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
1314           * @private
1315           * @deprecated This wrapper isn't that useful
1316           * @static
1317           */
1318          getElWrapper: function(id) {
1319              var oWrapper = this.elementCache[id];
1320              if (!oWrapper || !oWrapper.el) {
1321                  oWrapper = this.elementCache[id] = 
1322                      new this.ElementWrapper(YAHOO.util.Dom.get(id));
1323              }
1324              return oWrapper;
1325          },
1326  
1327          /**
1328           * Returns the actual DOM element
1329           * @method getElement
1330           * @param {String} id the id of the elment to get
1331           * @return {Object} The element
1332           * @deprecated use YAHOO.util.Dom.get instead
1333           * @static
1334           */
1335          getElement: function(id) {
1336              return YAHOO.util.Dom.get(id);
1337          },
1338          
1339          /**
1340           * Returns the style property for the DOM element (i.e., 
1341           * document.getElById(id).style)
1342           * @method getCss
1343           * @param {String} id the id of the elment to get
1344           * @return {Object} The style property of the element
1345           * @deprecated use YAHOO.util.Dom instead
1346           * @static
1347           */
1348          getCss: function(id) {
1349              var el = YAHOO.util.Dom.get(id);
1350              return (el) ? el.style : null;
1351          },
1352  
1353          /**
1354           * Inner class for cached elements
1355           * @class DragDropMgr.ElementWrapper
1356           * @for DragDropMgr
1357           * @private
1358           * @deprecated
1359           */
1360          ElementWrapper: function(el) {
1361                  /**
1362                   * The element
1363                   * @property el
1364                   */
1365                  this.el = el || null;
1366                  /**
1367                   * The element id
1368                   * @property id
1369                   */
1370                  this.id = this.el && el.id;
1371                  /**
1372                   * A reference to the style property
1373                   * @property css
1374                   */
1375                  this.css = this.el && el.style;
1376              },
1377  
1378          /**
1379           * Returns the X position of an html element
1380           * @method getPosX
1381           * @param el the element for which to get the position
1382           * @return {int} the X coordinate
1383           * @for DragDropMgr
1384           * @deprecated use YAHOO.util.Dom.getX instead
1385           * @static
1386           */
1387          getPosX: function(el) {
1388              return YAHOO.util.Dom.getX(el);
1389          },
1390  
1391          /**
1392           * Returns the Y position of an html element
1393           * @method getPosY
1394           * @param el the element for which to get the position
1395           * @return {int} the Y coordinate
1396           * @deprecated use YAHOO.util.Dom.getY instead
1397           * @static
1398           */
1399          getPosY: function(el) {
1400              return YAHOO.util.Dom.getY(el); 
1401          },
1402  
1403          /**
1404           * Swap two nodes.  In IE, we use the native method, for others we 
1405           * emulate the IE behavior
1406           * @method swapNode
1407           * @param n1 the first node to swap
1408           * @param n2 the other node to swap
1409           * @static
1410           */
1411          swapNode: function(n1, n2) {
1412              if (n1.swapNode) {
1413                  n1.swapNode(n2);
1414              } else {
1415                  var p = n2.parentNode;
1416                  var s = n2.nextSibling;
1417  
1418                  if (s == n1) {
1419                      p.insertBefore(n1, n2);
1420                  } else if (n2 == n1.nextSibling) {
1421                      p.insertBefore(n2, n1);
1422                  } else {
1423                      n1.parentNode.replaceChild(n2, n1);
1424                      p.insertBefore(n1, s);
1425                  }
1426              }
1427          },
1428  
1429          /**
1430           * Returns the current scroll position
1431           * @method getScroll
1432           * @private
1433           * @static
1434           */
1435          getScroll: function () {
1436              var t, l, dde=document.documentElement, db=document.body;
1437              if (dde && (dde.scrollTop || dde.scrollLeft)) {
1438                  t = dde.scrollTop;
1439                  l = dde.scrollLeft;
1440              } else if (db) {
1441                  t = db.scrollTop;
1442                  l = db.scrollLeft;
1443              } else {
1444                  YAHOO.log("could not get scroll property", "info", "DragDropMgr");
1445              }
1446              return { top: t, left: l };
1447          },
1448  
1449          /**
1450           * Returns the specified element style property
1451           * @method getStyle
1452           * @param {HTMLElement} el          the element
1453           * @param {string}      styleProp   the style property
1454           * @return {string} The value of the style property
1455           * @deprecated use YAHOO.util.Dom.getStyle
1456           * @static
1457           */
1458          getStyle: function(el, styleProp) {
1459              return YAHOO.util.Dom.getStyle(el, styleProp);
1460          },
1461  
1462          /**
1463           * Gets the scrollTop
1464           * @method getScrollTop
1465           * @return {int} the document's scrollTop
1466           * @static
1467           */
1468          getScrollTop: function () { return this.getScroll().top; },
1469  
1470          /**
1471           * Gets the scrollLeft
1472           * @method getScrollLeft
1473           * @return {int} the document's scrollTop
1474           * @static
1475           */
1476          getScrollLeft: function () { return this.getScroll().left; },
1477  
1478          /**
1479           * Sets the x/y position of an element to the location of the
1480           * target element.
1481           * @method moveToEl
1482           * @param {HTMLElement} moveEl      The element to move
1483           * @param {HTMLElement} targetEl    The position reference element
1484           * @static
1485           */
1486          moveToEl: function (moveEl, targetEl) {
1487              var aCoord = YAHOO.util.Dom.getXY(targetEl);
1488              YAHOO.log("moveToEl: " + aCoord, "info", "DragDropMgr");
1489              YAHOO.util.Dom.setXY(moveEl, aCoord);
1490          },
1491  
1492          /**
1493           * Gets the client height
1494           * @method getClientHeight
1495           * @return {int} client height in px
1496           * @deprecated use YAHOO.util.Dom.getViewportHeight instead
1497           * @static
1498           */
1499          getClientHeight: function() {
1500              return YAHOO.util.Dom.getViewportHeight();
1501          },
1502  
1503          /**
1504           * Gets the client width
1505           * @method getClientWidth
1506           * @return {int} client width in px
1507           * @deprecated use YAHOO.util.Dom.getViewportWidth instead
1508           * @static
1509           */
1510          getClientWidth: function() {
1511              return YAHOO.util.Dom.getViewportWidth();
1512          },
1513  
1514          /**
1515           * Numeric array sort function
1516           * @method numericSort
1517           * @static
1518           */
1519          numericSort: function(a, b) { return (a - b); },
1520  
1521          /**
1522           * Internal counter
1523           * @property _timeoutCount
1524           * @private
1525           * @static
1526           */
1527          _timeoutCount: 0,
1528  
1529          /**
1530           * Trying to make the load order less important.  Without this we get
1531           * an error if this file is loaded before the Event Utility.
1532           * @method _addListeners
1533           * @private
1534           * @static
1535           */
1536          _addListeners: function() {
1537              var DDM = YAHOO.util.DDM;
1538              if ( YAHOO.util.Event && document ) {
1539                  DDM._onLoad();
1540              } else {
1541                  if (DDM._timeoutCount > 2000) {
1542                      YAHOO.log("DragDrop requires the Event Utility", "error", "DragDropMgr");
1543                  } else {
1544                      setTimeout(DDM._addListeners, 10);
1545                      if (document && document.body) {
1546                          DDM._timeoutCount += 1;
1547                      }
1548                  }
1549              }
1550          },
1551  
1552          /**
1553           * Recursively searches the immediate parent and all child nodes for 
1554           * the handle element in order to determine wheter or not it was 
1555           * clicked.
1556           * @method handleWasClicked
1557           * @param node the html element to inspect
1558           * @static
1559           */
1560          handleWasClicked: function(node, id) {
1561              if (this.isHandle(id, node.id)) {
1562                  YAHOO.log("clicked node is a handle", "info", "DragDropMgr");
1563                  return true;
1564              } else {
1565                  // check to see if this is a text node child of the one we want
1566                  var p = node.parentNode;
1567                  // YAHOO.log("p: " + p);
1568  
1569                  while (p) {
1570                      if (this.isHandle(id, p.id)) {
1571                          return true;
1572                      } else {
1573                          YAHOO.log(p.id + " is not a handle", "info", "DragDropMgr");
1574                          p = p.parentNode;
1575                      }
1576                  }
1577              }
1578  
1579              return false;
1580          }
1581  
1582      };
1583  
1584  }();
1585  
1586  // shorter alias, save a few bytes
1587  YAHOO.util.DDM = YAHOO.util.DragDropMgr;
1588  YAHOO.util.DDM._addListeners();
1589  
1590  }
1591  
1592  (function() {
1593  
1594  var Event=YAHOO.util.Event; 
1595  var Dom=YAHOO.util.Dom;
1596  
1597  /**
1598   * Defines the interface and base operation of items that that can be 
1599   * dragged or can be drop targets.  It was designed to be extended, overriding
1600   * the event handlers for startDrag, onDrag, onDragOver, onDragOut.
1601   * Up to three html elements can be associated with a DragDrop instance:
1602   * <ul>
1603   * <li>linked element: the element that is passed into the constructor.
1604   * This is the element which defines the boundaries for interaction with 
1605   * other DragDrop objects.</li>
1606   * <li>handle element(s): The drag operation only occurs if the element that 
1607   * was clicked matches a handle element.  By default this is the linked 
1608   * element, but there are times that you will want only a portion of the 
1609   * linked element to initiate the drag operation, and the setHandleElId() 
1610   * method provides a way to define this.</li>
1611   * <li>drag element: this represents an the element that would be moved along
1612   * with the cursor during a drag operation.  By default, this is the linked
1613   * element itself as in {@link YAHOO.util.DD}.  setDragElId() lets you define
1614   * a separate element that would be moved, as in {@link YAHOO.util.DDProxy}
1615   * </li>
1616   * </ul>
1617   * This class should not be instantiated until the onload event to ensure that
1618   * the associated elements are available.
1619   * The following would define a DragDrop obj that would interact with any 
1620   * other DragDrop obj in the "group1" group:
1621   * <pre>
1622   *  dd = new YAHOO.util.DragDrop("div1", "group1");
1623   * </pre>
1624   * Since none of the event handlers have been implemented, nothing would 
1625   * actually happen if you were to run the code above.  Normally you would 
1626   * override this class or one of the default implementations, but you can 
1627   * also override the methods you want on an instance of the class...
1628   * <pre>
1629   *  dd.onDragDrop = function(e, id) {
1630   *  &nbsp;&nbsp;alert("dd was dropped on " + id);
1631   *  }
1632   * </pre>
1633   * @namespace YAHOO.util
1634   * @class DragDrop
1635   * @constructor
1636   * @param {String} id of the element that is linked to this instance
1637   * @param {String} sGroup the group of related DragDrop objects
1638   * @param {object} config an object containing configurable attributes
1639   *                Valid properties for DragDrop: 
1640   *                    padding, isTarget, maintainOffset, primaryButtonOnly,
1641   */
1642  YAHOO.util.DragDrop = function(id, sGroup, config) {
1643      if (id) {
1644          this.init(id, sGroup, config); 
1645      }
1646  };
1647  
1648  YAHOO.util.DragDrop.prototype = {
1649      /**
1650       * An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop
1651       * By setting any of these to false, then event will not be fired.
1652       * @property events
1653       * @type object
1654       */
1655      events: null,
1656      /**
1657      * @method on
1658      * @description Shortcut for EventProvider.subscribe, see <a href="YAHOO.util.EventProvider.html#subscribe">YAHOO.util.EventProvider.subscribe</a>
1659      */
1660      on: function() {
1661          this.subscribe.apply(this, arguments);
1662      },
1663      /**
1664       * The id of the element associated with this object.  This is what we 
1665       * refer to as the "linked element" because the size and position of 
1666       * this element is used to determine when the drag and drop objects have 
1667       * interacted.
1668       * @property id
1669       * @type String
1670       */
1671      id: null,
1672  
1673      /**
1674       * Configuration attributes passed into the constructor
1675       * @property config
1676       * @type object
1677       */
1678      config: null,
1679  
1680      /**
1681       * The id of the element that will be dragged.  By default this is same 
1682       * as the linked element , but could be changed to another element. Ex: 
1683       * YAHOO.util.DDProxy
1684       * @property dragElId
1685       * @type String
1686       * @private
1687       */
1688      dragElId: null, 
1689  
1690      /**
1691       * the id of the element that initiates the drag operation.  By default 
1692       * this is the linked element, but could be changed to be a child of this
1693       * element.  This lets us do things like only starting the drag when the 
1694       * header element within the linked html element is clicked.
1695       * @property handleElId
1696       * @type String
1697       * @private
1698       */
1699      handleElId: null, 
1700  
1701      /**
1702       * An associative array of HTML tags that will be ignored if clicked.
1703       * @property invalidHandleTypes
1704       * @type {string: string}
1705       */
1706      invalidHandleTypes: null, 
1707  
1708      /**
1709       * An associative array of ids for elements that will be ignored if clicked
1710       * @property invalidHandleIds
1711       * @type {string: string}
1712       */
1713      invalidHandleIds: null, 
1714  
1715      /**
1716       * An indexted array of css class names for elements that will be ignored
1717       * if clicked.
1718       * @property invalidHandleClasses
1719       * @type string[]
1720       */
1721      invalidHandleClasses: null, 
1722  
1723      /**
1724       * The linked element's absolute X position at the time the drag was 
1725       * started
1726       * @property startPageX
1727       * @type int
1728       * @private
1729       */
1730      startPageX: 0,
1731  
1732      /**
1733       * The linked element's absolute X position at the time the drag was 
1734       * started
1735       * @property startPageY
1736       * @type int
1737       * @private
1738       */
1739      startPageY: 0,
1740  
1741      /**
1742       * The group defines a logical collection of DragDrop objects that are 
1743       * related.  Instances only get events when interacting with other 
1744       * DragDrop object in the same group.  This lets us define multiple 
1745       * groups using a single DragDrop subclass if we want.
1746       * @property groups
1747       * @type {string: string}
1748       */
1749      groups: null,
1750  
1751      /**
1752       * Individual drag/drop instances can be locked.  This will prevent 
1753       * onmousedown start drag.
1754       * @property locked
1755       * @type boolean
1756       * @private
1757       */
1758      locked: false,
1759  
1760      /**
1761       * Lock this instance
1762       * @method lock
1763       */
1764      lock: function() { this.locked = true; },
1765  
1766      /**
1767       * Unlock this instace
1768       * @method unlock
1769       */
1770      unlock: function() { this.locked = false; },
1771  
1772      /**
1773       * By default, all instances can be a drop target.  This can be disabled by
1774       * setting isTarget to false.
1775       * @property isTarget
1776       * @type boolean
1777       */
1778      isTarget: true,
1779  
1780      /**
1781       * The padding configured for this drag and drop object for calculating
1782       * the drop zone intersection with this object.
1783       * @property padding
1784       * @type int[]
1785       */
1786      padding: null,
1787      /**
1788       * If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)
1789       * @property dragOnly
1790       * @type Boolean
1791       */
1792      dragOnly: false,
1793  
1794      /**
1795       * If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls.
1796       * @property useShim
1797       * @type Boolean
1798       */
1799      useShim: false,
1800  
1801      /**
1802       * Cached reference to the linked element
1803       * @property _domRef
1804       * @private
1805       */
1806      _domRef: null,
1807  
1808      /**
1809       * Internal typeof flag
1810       * @property __ygDragDrop
1811       * @private
1812       */
1813      __ygDragDrop: true,
1814  
1815      /**
1816       * Set to true when horizontal contraints are applied
1817       * @property constrainX
1818       * @type boolean
1819       * @private
1820       */
1821      constrainX: false,
1822  
1823      /**
1824       * Set to true when vertical contraints are applied
1825       * @property constrainY
1826       * @type boolean
1827       * @private
1828       */
1829      constrainY: false,
1830  
1831      /**
1832       * The left constraint
1833       * @property minX
1834       * @type int
1835       * @private
1836       */
1837      minX: 0,
1838  
1839      /**
1840       * The right constraint
1841       * @property maxX
1842       * @type int
1843       * @private
1844       */
1845      maxX: 0,
1846  
1847      /**
1848       * The up constraint 
1849       * @property minY
1850       * @type int
1851       * @type int
1852       * @private
1853       */
1854      minY: 0,
1855  
1856      /**
1857       * The down constraint 
1858       * @property maxY
1859       * @type int
1860       * @private
1861       */
1862      maxY: 0,
1863  
1864      /**
1865       * The difference between the click position and the source element's location
1866       * @property deltaX
1867       * @type int
1868       * @private
1869       */
1870      deltaX: 0,
1871  
1872      /**
1873       * The difference between the click position and the source element's location
1874       * @property deltaY
1875       * @type int
1876       * @private
1877       */
1878      deltaY: 0,
1879  
1880      /**
1881       * Maintain offsets when we resetconstraints.  Set to true when you want
1882       * the position of the element relative to its parent to stay the same
1883       * when the page changes
1884       *
1885       * @property maintainOffset
1886       * @type boolean
1887       */
1888      maintainOffset: false,
1889  
1890      /**
1891       * Array of pixel locations the element will snap to if we specified a 
1892       * horizontal graduation/interval.  This array is generated automatically
1893       * when you define a tick interval.
1894       * @property xTicks
1895       * @type int[]
1896       */
1897      xTicks: null,
1898  
1899      /**
1900       * Array of pixel locations the element will snap to if we specified a 
1901       * vertical graduation/interval.  This array is generated automatically 
1902       * when you define a tick interval.
1903       * @property yTicks
1904       * @type int[]
1905       */
1906      yTicks: null,
1907  
1908      /**
1909       * By default the drag and drop instance will only respond to the primary
1910       * button click (left button for a right-handed mouse).  Set to true to
1911       * allow drag and drop to start with any mouse click that is propogated
1912       * by the browser
1913       * @property primaryButtonOnly
1914       * @type boolean
1915       */
1916      primaryButtonOnly: true,
1917  
1918      /**
1919       * The availabe property is false until the linked dom element is accessible.
1920       * @property available
1921       * @type boolean
1922       */
1923      available: false,
1924  
1925      /**
1926       * By default, drags can only be initiated if the mousedown occurs in the
1927       * region the linked element is.  This is done in part to work around a
1928       * bug in some browsers that mis-report the mousedown if the previous
1929       * mouseup happened outside of the window.  This property is set to true
1930       * if outer handles are defined.
1931       *
1932       * @property hasOuterHandles
1933       * @type boolean
1934       * @default false
1935       */
1936      hasOuterHandles: false,
1937  
1938      /**
1939       * Property that is assigned to a drag and drop object when testing to
1940       * see if it is being targeted by another dd object.  This property
1941       * can be used in intersect mode to help determine the focus of
1942       * the mouse interaction.  DDM.getBestMatch uses this property first to
1943       * determine the closest match in INTERSECT mode when multiple targets
1944       * are part of the same interaction.
1945       * @property cursorIsOver
1946       * @type boolean
1947       */
1948      cursorIsOver: false,
1949  
1950      /**
1951       * Property that is assigned to a drag and drop object when testing to
1952       * see if it is being targeted by another dd object.  This is a region
1953       * that represents the area the draggable element overlaps this target.
1954       * DDM.getBestMatch uses this property to compare the size of the overlap
1955       * to that of other targets in order to determine the closest match in
1956       * INTERSECT mode when multiple targets are part of the same interaction.
1957       * @property overlap 
1958       * @type YAHOO.util.Region
1959       */
1960      overlap: null,
1961  
1962      /**
1963       * Code that executes immediately before the startDrag event
1964       * @method b4StartDrag
1965       * @private
1966       */
1967      b4StartDrag: function(x, y) { },
1968  
1969      /**
1970       * Abstract method called after a drag/drop object is clicked
1971       * and the drag or mousedown time thresholds have beeen met.
1972       * @method startDrag
1973       * @param {int} X click location
1974       * @param {int} Y click location
1975       */
1976      startDrag: function(x, y) { /* override this */ },
1977  
1978      /**
1979       * Code that executes immediately before the onDrag event
1980       * @method b4Drag
1981       * @private
1982       */
1983      b4Drag: function(e) { },
1984  
1985      /**
1986       * Abstract method called during the onMouseMove event while dragging an 
1987       * object.
1988       * @method onDrag
1989       * @param {Event} e the mousemove event
1990       */
1991      onDrag: function(e) { /* override this */ },
1992  
1993      /**
1994       * Abstract method called when this element fist begins hovering over 
1995       * another DragDrop obj
1996       * @method onDragEnter
1997       * @param {Event} e the mousemove event
1998       * @param {String|DragDrop[]} id In POINT mode, the element
1999       * id this is hovering over.  In INTERSECT mode, an array of one or more 
2000       * dragdrop items being hovered over.
2001       */
2002      onDragEnter: function(e, id) { /* override this */ },
2003  
2004      /**
2005       * Code that executes immediately before the onDragOver event
2006       * @method b4DragOver
2007       * @private
2008       */
2009      b4DragOver: function(e) { },
2010  
2011      /**
2012       * Abstract method called when this element is hovering over another 
2013       * DragDrop obj
2014       * @method onDragOver
2015       * @param {Event} e the mousemove event
2016       * @param {String|DragDrop[]} id In POINT mode, the element
2017       * id this is hovering over.  In INTERSECT mode, an array of dd items 
2018       * being hovered over.
2019       */
2020      onDragOver: function(e, id) { /* override this */ },
2021  
2022      /**
2023       * Code that executes immediately before the onDragOut event
2024       * @method b4DragOut
2025       * @private
2026       */
2027      b4DragOut: function(e) { },
2028  
2029      /**
2030       * Abstract method called when we are no longer hovering over an element
2031       * @method onDragOut
2032       * @param {Event} e the mousemove event
2033       * @param {String|DragDrop[]} id In POINT mode, the element
2034       * id this was hovering over.  In INTERSECT mode, an array of dd items 
2035       * that the mouse is no longer over.
2036       */
2037      onDragOut: function(e, id) { /* override this */ },
2038  
2039      /**
2040       * Code that executes immediately before the onDragDrop event
2041       * @method b4DragDrop
2042       * @private
2043       */
2044      b4DragDrop: function(e) { },
2045  
2046      /**
2047       * Abstract method called when this item is dropped on another DragDrop 
2048       * obj
2049       * @method onDragDrop
2050       * @param {Event} e the mouseup event
2051       * @param {String|DragDrop[]} id In POINT mode, the element
2052       * id this was dropped on.  In INTERSECT mode, an array of dd items this 
2053       * was dropped on.
2054       */
2055      onDragDrop: function(e, id) { /* override this */ },
2056  
2057      /**
2058       * Abstract method called when this item is dropped on an area with no
2059       * drop target
2060       * @method onInvalidDrop
2061       * @param {Event} e the mouseup event
2062       */
2063      onInvalidDrop: function(e) { /* override this */ },
2064  
2065      /**
2066       * Code that executes immediately before the endDrag event
2067       * @method b4EndDrag
2068       * @private
2069       */
2070      b4EndDrag: function(e) { },
2071  
2072      /**
2073       * Fired when we are done dragging the object
2074       * @method endDrag
2075       * @param {Event} e the mouseup event
2076       */
2077      endDrag: function(e) { /* override this */ },
2078  
2079      /**
2080       * Code executed immediately before the onMouseDown event
2081       * @method b4MouseDown
2082       * @param {Event} e the mousedown event
2083       * @private
2084       */
2085      b4MouseDown: function(e) {  },
2086  
2087      /**
2088       * Event handler that fires when a drag/drop obj gets a mousedown
2089       * @method onMouseDown
2090       * @param {Event} e the mousedown event
2091       */
2092      onMouseDown: function(e) { /* override this */ },
2093  
2094      /**
2095       * Event handler that fires when a drag/drop obj gets a mouseup
2096       * @method onMouseUp
2097       * @param {Event} e the mouseup event
2098       */
2099      onMouseUp: function(e) { /* override this */ },
2100     
2101      /**
2102       * Override the onAvailable method to do what is needed after the initial
2103       * position was determined.
2104       * @method onAvailable
2105       */
2106      onAvailable: function () { 
2107          //this.logger.log("onAvailable (base)"); 
2108      },
2109  
2110      /**
2111       * Returns a reference to the linked element
2112       * @method getEl
2113       * @return {HTMLElement} the html element 
2114       */
2115      getEl: function() { 
2116          if (!this._domRef) {
2117              this._domRef = Dom.get(this.id); 
2118          }
2119  
2120          return this._domRef;
2121      },
2122  
2123      /**
2124       * Returns a reference to the actual element to drag.  By default this is
2125       * the same as the html element, but it can be assigned to another 
2126       * element. An example of this can be found in YAHOO.util.DDProxy
2127       * @method getDragEl
2128       * @return {HTMLElement} the html element 
2129       */
2130      getDragEl: function() {
2131          return Dom.get(this.dragElId);
2132      },
2133  
2134      /**
2135       * Sets up the DragDrop object.  Must be called in the constructor of any
2136       * YAHOO.util.DragDrop subclass
2137       * @method init
2138       * @param id the id of the linked element
2139       * @param {String} sGroup the group of related items
2140       * @param {object} config configuration attributes
2141       */
2142      init: function(id, sGroup, config) {
2143          this.initTarget(id, sGroup, config);
2144          Event.on(this._domRef || this.id, "mousedown", 
2145                          this.handleMouseDown, this, true);
2146  
2147          // Event.on(this.id, "selectstart", Event.preventDefault);
2148          for (var i in this.events) {
2149              this.createEvent(i + 'Event');
2150          }
2151          
2152      },
2153  
2154      /**
2155       * Initializes Targeting functionality only... the object does not
2156       * get a mousedown handler.
2157       * @method initTarget
2158       * @param id the id of the linked element
2159       * @param {String} sGroup the group of related items
2160       * @param {object} config configuration attributes
2161       */
2162      initTarget: function(id, sGroup, config) {
2163  
2164          // configuration attributes 
2165          this.config = config || {};
2166  
2167          this.events = {};
2168  
2169          // create a local reference to the drag and drop manager
2170          this.DDM = YAHOO.util.DDM;
2171  
2172          // initialize the groups object
2173          this.groups = {};
2174  
2175          // assume that we have an element reference instead of an id if the
2176          // parameter is not a string
2177          if (typeof id !== "string") {
2178              YAHOO.log("id is not a string, assuming it is an HTMLElement");
2179              this._domRef = id;
2180              id = Dom.generateId(id);
2181          }
2182  
2183          // set the id
2184          this.id = id;
2185  
2186          // add to an interaction group
2187          this.addToGroup((sGroup) ? sGroup : "default");
2188  
2189          // We don't want to register this as the handle with the manager
2190          // so we just set the id rather than calling the setter.
2191          this.handleElId = id;
2192  
2193          Event.onAvailable(id, this.handleOnAvailable, this, true);
2194  
2195          // create a logger instance
2196          this.logger = (YAHOO.widget.LogWriter) ? 
2197                  new YAHOO.widget.LogWriter(this.toString()) : YAHOO;
2198  
2199          // the linked element is the element that gets dragged by default
2200          this.setDragElId(id); 
2201  
2202          // by default, clicked anchors will not start drag operations. 
2203          // @TODO what else should be here?  Probably form fields.
2204          this.invalidHandleTypes = { A: "A" };
2205          this.invalidHandleIds = {};
2206          this.invalidHandleClasses = [];
2207  
2208          this.applyConfig();
2209      },
2210  
2211      /**
2212       * Applies the configuration parameters that were passed into the constructor.
2213       * This is supposed to happen at each level through the inheritance chain.  So
2214       * a DDProxy implentation will execute apply config on DDProxy, DD, and 
2215       * DragDrop in order to get all of the parameters that are available in
2216       * each object.
2217       * @method applyConfig
2218       */
2219      applyConfig: function() {
2220          this.events = {
2221              mouseDown: true,
2222              b4MouseDown: true,
2223              mouseUp: true,
2224              b4StartDrag: true,
2225              startDrag: true,
2226              b4EndDrag: true,
2227              endDrag: true,
2228              drag: true,
2229              b4Drag: true,
2230              invalidDrop: true,
2231              b4DragOut: true,
2232              dragOut: true,
2233              dragEnter: true,
2234              b4DragOver: true,
2235              dragOver: true,
2236              b4DragDrop: true,
2237              dragDrop: true
2238          };
2239          
2240          if (this.config.events) {
2241              for (var i in this.config.events) {
2242                  if (this.config.events[i] === false) {
2243                      this.events[i] = false;
2244                  }
2245              }
2246          }
2247  
2248  
2249          // configurable properties: 
2250          //    padding, isTarget, maintainOffset, primaryButtonOnly
2251          this.padding           = this.config.padding || [0, 0, 0, 0];
2252          this.isTarget          = (this.config.isTarget !== false);
2253          this.maintainOffset    = (this.config.maintainOffset);
2254          this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
2255          this.dragOnly = ((this.config.dragOnly === true) ? true : false);
2256          this.useShim = ((this.config.useShim === true) ? true : false);
2257      },
2258  
2259      /**
2260       * Executed when the linked element is available
2261       * @method handleOnAvailable
2262       * @private
2263       */
2264      handleOnAvailable: function() {
2265          //this.logger.log("handleOnAvailable");
2266          this.available = true;
2267          this.resetConstraints();
2268          this.onAvailable();
2269      },
2270  
2271       /**
2272       * Configures the padding for the target zone in px.  Effectively expands
2273       * (or reduces) the virtual object size for targeting calculations.  
2274       * Supports css-style shorthand; if only one parameter is passed, all sides
2275       * will have that padding, and if only two are passed, the top and bottom
2276       * will have the first param, the left and right the second.
2277       * @method setPadding
2278       * @param {int} iTop    Top pad
2279       * @param {int} iRight  Right pad
2280       * @param {int} iBot    Bot pad
2281       * @param {int} iLeft   Left pad
2282       */
2283      setPadding: function(iTop, iRight, iBot, iLeft) {
2284          // this.padding = [iLeft, iRight, iTop, iBot];
2285          if (!iRight && 0 !== iRight) {
2286              this.padding = [iTop, iTop, iTop, iTop];
2287          } else if (!iBot && 0 !== iBot) {
2288              this.padding = [iTop, iRight, iTop, iRight];
2289          } else {
2290              this.padding = [iTop, iRight, iBot, iLeft];
2291          }
2292      },
2293  
2294      /**
2295       * Stores the initial placement of the linked element.
2296       * @method setInitialPosition
2297       * @param {int} diffX   the X offset, default 0
2298       * @param {int} diffY   the Y offset, default 0
2299       * @private
2300       */
2301      setInitPosition: function(diffX, diffY) {
2302          var el = this.getEl();
2303  
2304          if (!this.DDM.verifyEl(el)) {
2305              if (el && el.style && (el.style.display == 'none')) {
2306                  this.logger.log(this.id + " can not get initial position, element style is display: none");
2307              } else {
2308                  this.logger.log(this.id + " element is broken");
2309              }
2310              return;
2311          }
2312  
2313          var dx = diffX || 0;
2314          var dy = diffY || 0;
2315  
2316          var p = Dom.getXY( el );
2317  
2318          this.initPageX = p[0] - dx;
2319          this.initPageY = p[1] - dy;
2320  
2321          this.lastPageX = p[0];
2322          this.lastPageY = p[1];
2323  
2324          this.logger.log(this.id + " initial position: " + this.initPageX + 
2325                  ", " + this.initPageY);
2326  
2327  
2328          this.setStartPosition(p);
2329      },
2330  
2331      /**
2332       * Sets the start position of the element.  This is set when the obj
2333       * is initialized, the reset when a drag is started.
2334       * @method setStartPosition
2335       * @param pos current position (from previous lookup)
2336       * @private
2337       */
2338      setStartPosition: function(pos) {
2339          var p = pos || Dom.getXY(this.getEl());
2340  
2341          this.deltaSetXY = null;
2342  
2343          this.startPageX = p[0];
2344          this.startPageY = p[1];
2345      },
2346  
2347      /**
2348       * Add this instance to a group of related drag/drop objects.  All 
2349       * instances belong to at least one group, and can belong to as many 
2350       * groups as needed.
2351       * @method addToGroup
2352       * @param sGroup {string} the name of the group
2353       */
2354      addToGroup: function(sGroup) {
2355          this.groups[sGroup] = true;
2356          this.DDM.regDragDrop(this, sGroup);
2357      },
2358  
2359      /**
2360       * Remove's this instance from the supplied interaction group
2361       * @method removeFromGroup
2362       * @param {string}  sGroup  The group to drop
2363       */
2364      removeFromGroup: function(sGroup) {
2365          this.logger.log("Removing from group: " + sGroup);
2366          if (this.groups[sGroup]) {
2367              delete this.groups[sGroup];
2368          }
2369  
2370          this.DDM.removeDDFromGroup(this, sGroup);
2371      },
2372  
2373      /**
2374       * Allows you to specify that an element other than the linked element 
2375       * will be moved with the cursor during a drag
2376       * @method setDragElId
2377       * @param id {string} the id of the element that will be used to initiate the drag
2378       */
2379      setDragElId: function(id) {
2380          this.dragElId = id;
2381      },
2382  
2383      /**
2384       * Allows you to specify a child of the linked element that should be 
2385       * used to initiate the drag operation.  An example of this would be if 
2386       * you have a content div with text and links.  Clicking anywhere in the 
2387       * content area would normally start the drag operation.  Use this method
2388       * to specify that an element inside of the content div is the element 
2389       * that starts the drag operation.
2390       * @method setHandleElId
2391       * @param id {string} the id of the element that will be used to 
2392       * initiate the drag.
2393       */
2394      setHandleElId: function(id) {
2395          if (typeof id !== "string") {
2396              YAHOO.log("id is not a string, assuming it is an HTMLElement");
2397              id = Dom.generateId(id);
2398          }
2399          this.handleElId = id;
2400          this.DDM.regHandle(this.id, id);
2401      },
2402  
2403      /**
2404       * Allows you to set an element outside of the linked element as a drag 
2405       * handle
2406       * @method setOuterHandleElId
2407       * @param id the id of the element that will be used to initiate the drag
2408       */
2409      setOuterHandleElId: function(id) {
2410          if (typeof id !== "string") {
2411              YAHOO.log("id is not a string, assuming it is an HTMLElement");
2412              id = Dom.generateId(id);
2413          }
2414          this.logger.log("Adding outer handle event: " + id);
2415          Event.on(id, "mousedown", 
2416                  this.handleMouseDown, this, true);
2417          this.setHandleElId(id);
2418  
2419          this.hasOuterHandles = true;
2420      },
2421  
2422      /**
2423       * Remove all drag and drop hooks for this element
2424       * @method unreg
2425       */
2426      unreg: function() {
2427          this.logger.log("DragDrop obj cleanup " + this.id);
2428          Event.removeListener(this.id, "mousedown", 
2429                  this.handleMouseDown);
2430          this._domRef = null;
2431          this.DDM._remove(this);
2432      },
2433  
2434      /**
2435       * Returns true if this instance is locked, or the drag drop mgr is locked
2436       * (meaning that all drag/drop is disabled on the page.)
2437       * @method isLocked
2438       * @return {boolean} true if this obj or all drag/drop is locked, else 
2439       * false
2440       */
2441      isLocked: function() {
2442          return (this.DDM.isLocked() || this.locked);
2443      },
2444  
2445      /**
2446       * Fired when this object is clicked
2447       * @method handleMouseDown
2448       * @param {Event} e 
2449       * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
2450       * @private
2451       */
2452      handleMouseDown: function(e, oDD) {
2453  
2454          var button = e.which || e.button;
2455          this.logger.log("button: " + button);
2456  
2457          if (this.primaryButtonOnly && button > 1) {
2458              this.logger.log("Mousedown was not produced by the primary button");
2459              return;
2460          }
2461  
2462          if (this.isLocked()) {
2463              this.logger.log("Drag and drop is disabled, aborting");
2464              return;
2465          }
2466  
2467          this.logger.log("mousedown " + this.id);
2468  
2469          this.logger.log("firing onMouseDown events");
2470  
2471          // firing the mousedown events prior to calculating positions
2472          var b4Return = this.b4MouseDown(e),
2473          b4Return2 = true;
2474  
2475          if (this.events.b4MouseDown) {
2476              b4Return2 = this.fireEvent('b4MouseDownEvent', e);
2477          }
2478          var mDownReturn = this.onMouseDown(e),
2479              mDownReturn2 = true;
2480          if (this.events.mouseDown) {
2481              if (mDownReturn === false) {
2482                  //Fixes #2528759 - Mousedown function returned false, don't fire the event and cancel everything.
2483                   mDownReturn2 = false;
2484              } else {
2485                  mDownReturn2 = this.fireEvent('mouseDownEvent', e);
2486              }
2487          }
2488  
2489          if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) {
2490              this.logger.log('b4MouseDown or onMouseDown returned false, exiting drag');
2491              return;
2492          }
2493  
2494          this.DDM.refreshCache(this.groups);
2495          // var self = this;
2496          // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0);
2497  
2498          // Only process the event if we really clicked within the linked 
2499          // element.  The reason we make this check is that in the case that 
2500          // another element was moved between the clicked element and the 
2501          // cursor in the time between the mousedown and mouseup events. When 
2502          // this happens, the element gets the next mousedown event 
2503          // regardless of where on the screen it happened.  
2504          var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e));
2505          if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
2506                  this.logger.log("Click was not over the element: " + this.id);
2507          } else {
2508              if (this.clickValidator(e)) {
2509  
2510                  this.logger.log("click was a valid handle");
2511  
2512                  // set the initial element position
2513                  this.setStartPosition();
2514  
2515                  // start tracking mousemove distance and mousedown time to
2516                  // determine when to start the actual drag
2517                  this.DDM.handleMouseDown(e, this);
2518  
2519                  // this mousedown is mine
2520                  this.DDM.stopEvent(e);
2521              } else {
2522  
2523  this.logger.log("clickValidator returned false, drag not initiated");
2524  
2525              }
2526          }
2527      },
2528  
2529      /**
2530       * @method clickValidator
2531       * @description Method validates that the clicked element
2532       * was indeed the handle or a valid child of the handle
2533       * @param {Event} e 
2534       */
2535      clickValidator: function(e) {
2536          var target = YAHOO.util.Event.getTarget(e);
2537          return ( this.isValidHandleChild(target) &&
2538                      (this.id == this.handleElId || 
2539                          this.DDM.handleWasClicked(target, this.id)) );
2540      },
2541  
2542      /**
2543       * Finds the location the element should be placed if we want to move
2544       * it to where the mouse location less the click offset would place us.
2545       * @method getTargetCoord
2546       * @param {int} iPageX the X coordinate of the click
2547       * @param {int} iPageY the Y coordinate of the click
2548       * @return an object that contains the coordinates (Object.x and Object.y)
2549       * @private
2550       */
2551      getTargetCoord: function(iPageX, iPageY) {
2552  
2553          // this.logger.log("getTargetCoord: " + iPageX + ", " + iPageY);
2554  
2555          var x = iPageX - this.deltaX;
2556          var y = iPageY - this.deltaY;
2557  
2558          if (this.constrainX) {
2559              if (x < this.minX) { x = this.minX; }
2560              if (x > this.maxX) { x = this.maxX; }
2561          }
2562  
2563          if (this.constrainY) {
2564              if (y < this.minY) { y = this.minY; }
2565              if (y > this.maxY) { y = this.maxY; }
2566          }
2567  
2568          x = this.getTick(x, this.xTicks);
2569          y = this.getTick(y, this.yTicks);
2570  
2571          // this.logger.log("getTargetCoord " + 
2572                  // " iPageX: " + iPageX +
2573                  // " iPageY: " + iPageY +
2574                  // " x: " + x + ", y: " + y);
2575  
2576          return {x:x, y:y};
2577      },
2578  
2579      /**
2580       * Allows you to specify a tag name that should not start a drag operation
2581       * when clicked.  This is designed to facilitate embedding links within a
2582       * drag handle that do something other than start the drag.
2583       * @method addInvalidHandleType
2584       * @param {string} tagName the type of element to exclude
2585       */
2586      addInvalidHandleType: function(tagName) {
2587          var type = tagName.toUpperCase();
2588          this.invalidHandleTypes[type] = type;
2589      },
2590  
2591      /**
2592       * Lets you to specify an element id for a child of a drag handle
2593       * that should not initiate a drag
2594       * @method addInvalidHandleId
2595       * @param {string} id the element id of the element you wish to ignore
2596       */
2597      addInvalidHandleId: function(id) {
2598          if (typeof id !== "string") {
2599              YAHOO.log("id is not a string, assuming it is an HTMLElement");
2600              id = Dom.generateId(id);
2601          }
2602          this.invalidHandleIds[id] = id;
2603      },
2604  
2605  
2606      /**
2607       * Lets you specify a css class of elements that will not initiate a drag
2608       * @method addInvalidHandleClass
2609       * @param {string} cssClass the class of the elements you wish to ignore
2610       */
2611      addInvalidHandleClass: function(cssClass) {
2612          this.invalidHandleClasses.push(cssClass);
2613      },
2614  
2615      /**
2616       * Unsets an excluded tag name set by addInvalidHandleType
2617       * @method removeInvalidHandleType
2618       * @param {string} tagName the type of element to unexclude
2619       */
2620      removeInvalidHandleType: function(tagName) {
2621          var type = tagName.toUpperCase();
2622          // this.invalidHandleTypes[type] = null;
2623          delete this.invalidHandleTypes[type];
2624      },
2625      
2626      /**
2627       * Unsets an invalid handle id
2628       * @method removeInvalidHandleId
2629       * @param {string} id the id of the element to re-enable
2630       */
2631      removeInvalidHandleId: function(id) {
2632          if (typeof id !== "string") {
2633              YAHOO.log("id is not a string, assuming it is an HTMLElement");
2634              id = Dom.generateId(id);
2635          }
2636          delete this.invalidHandleIds[id];
2637      },
2638  
2639      /**
2640       * Unsets an invalid css class
2641       * @method removeInvalidHandleClass
2642       * @param {string} cssClass the class of the element(s) you wish to 
2643       * re-enable
2644       */
2645      removeInvalidHandleClass: function(cssClass) {
2646          for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
2647              if (this.invalidHandleClasses[i] == cssClass) {
2648                  delete this.invalidHandleClasses[i];
2649              }
2650          }
2651      },
2652  
2653      /**
2654       * Checks the tag exclusion list to see if this click should be ignored
2655       * @method isValidHandleChild
2656       * @param {HTMLElement} node the HTMLElement to evaluate
2657       * @return {boolean} true if this is a valid tag type, false if not
2658       */
2659      isValidHandleChild: function(node) {
2660  
2661          var valid = true;
2662          // var n = (node.nodeName == "#text") ? node.parentNode : node;
2663          var nodeName;
2664          try {
2665              nodeName = node.nodeName.toUpperCase();
2666          } catch(e) {
2667              nodeName = node.nodeName;
2668          }
2669          valid = valid && !this.invalidHandleTypes[nodeName];
2670          valid = valid && !this.invalidHandleIds[node.id];
2671  
2672          for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
2673              valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
2674          }
2675  
2676          this.logger.log("Valid handle? ... " + valid);
2677  
2678          return valid;
2679  
2680      },
2681  
2682      /**
2683       * Create the array of horizontal tick marks if an interval was specified
2684       * in setXConstraint().
2685       * @method setXTicks
2686       * @private
2687       */
2688      setXTicks: function(iStartX, iTickSize) {
2689          this.xTicks = [];
2690          this.xTickSize = iTickSize;
2691          
2692          var tickMap = {};
2693  
2694          for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
2695              if (!tickMap[i]) {
2696                  this.xTicks[this.xTicks.length] = i;
2697                  tickMap[i] = true;
2698              }
2699          }
2700  
2701          for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
2702              if (!tickMap[i]) {
2703                  this.xTicks[this.xTicks.length] = i;
2704                  tickMap[i] = true;
2705              }
2706          }
2707  
2708          this.xTicks.sort(this.DDM.numericSort) ;
2709          this.logger.log("xTicks: " + this.xTicks.join());
2710      },
2711  
2712      /**
2713       * Create the array of vertical tick marks if an interval was specified in 
2714       * setYConstraint().
2715       * @method setYTicks
2716       * @private
2717       */
2718      setYTicks: function(iStartY, iTickSize) {
2719          // this.logger.log("setYTicks: " + iStartY + ", " + iTickSize
2720                 // + ", " + this.initPageY + ", " + this.minY + ", " + this.maxY );
2721          this.yTicks = [];
2722          this.yTickSize = iTickSize;
2723  
2724          var tickMap = {};
2725  
2726          for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
2727              if (!tickMap[i]) {
2728                  this.yTicks[this.yTicks.length] = i;
2729                  tickMap[i] = true;
2730              }
2731          }
2732  
2733          for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
2734              if (!tickMap[i]) {
2735                  this.yTicks[this.yTicks.length] = i;
2736                  tickMap[i] = true;
2737              }
2738          }
2739  
2740          this.yTicks.sort(this.DDM.numericSort) ;
2741          this.logger.log("yTicks: " + this.yTicks.join());
2742      },
2743  
2744      /**
2745       * By default, the element can be dragged any place on the screen.  Use 
2746       * this method to limit the horizontal travel of the element.  Pass in 
2747       * 0,0 for the parameters if you want to lock the drag to the y axis.
2748       * @method setXConstraint
2749       * @param {int} iLeft the number of pixels the element can move to the left
2750       * @param {int} iRight the number of pixels the element can move to the 
2751       * right
2752       * @param {int} iTickSize optional parameter for specifying that the 
2753       * element
2754       * should move iTickSize pixels at a time.
2755       */
2756      setXConstraint: function(iLeft, iRight, iTickSize) {
2757          this.leftConstraint = parseInt(iLeft, 10);
2758          this.rightConstraint = parseInt(iRight, 10);
2759  
2760          this.minX = this.initPageX - this.leftConstraint;
2761          this.maxX = this.initPageX + this.rightConstraint;
2762          if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
2763  
2764          this.constrainX = true;
2765          this.logger.log("initPageX:" + this.initPageX + " minX:" + this.minX + 
2766                  " maxX:" + this.maxX);
2767      },
2768  
2769      /**
2770       * Clears any constraints applied to this instance.  Also clears ticks
2771       * since they can't exist independent of a constraint at this time.
2772       * @method clearConstraints
2773       */
2774      clearConstraints: function() {
2775          this.logger.log("Clearing constraints");
2776          this.constrainX = false;
2777          this.constrainY = false;
2778          this.clearTicks();
2779      },
2780  
2781      /**
2782       * Clears any tick interval defined for this instance
2783       * @method clearTicks
2784       */
2785      clearTicks: function() {
2786          this.logger.log("Clearing ticks");
2787          this.xTicks = null;
2788          this.yTicks = null;
2789          this.xTickSize = 0;
2790          this.yTickSize = 0;
2791      },
2792  
2793      /**
2794       * By default, the element can be dragged any place on the screen.  Set 
2795       * this to limit the vertical travel of the element.  Pass in 0,0 for the
2796       * parameters if you want to lock the drag to the x axis.
2797       * @method setYConstraint
2798       * @param {int} iUp the number of pixels the element can move up
2799       * @param {int} iDown the number of pixels the element can move down
2800       * @param {int} iTickSize optional parameter for specifying that the 
2801       * element should move iTickSize pixels at a time.
2802       */
2803      setYConstraint: function(iUp, iDown, iTickSize) {
2804          this.logger.log("setYConstraint: " + iUp + "," + iDown + "," + iTickSize);
2805          this.topConstraint = parseInt(iUp, 10);
2806          this.bottomConstraint = parseInt(iDown, 10);
2807  
2808          this.minY = this.initPageY - this.topConstraint;
2809          this.maxY = this.initPageY + this.bottomConstraint;
2810          if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
2811  
2812          this.constrainY = true;
2813          
2814          this.logger.log("initPageY:" + this.initPageY + " minY:" + this.minY + 
2815                  " maxY:" + this.maxY);
2816      },
2817  
2818      /**
2819       * resetConstraints must be called if you manually reposition a dd element.
2820       * @method resetConstraints
2821       */
2822      resetConstraints: function() {
2823  
2824          //this.logger.log("resetConstraints");
2825  
2826          // Maintain offsets if necessary
2827          if (this.initPageX || this.initPageX === 0) {
2828              //this.logger.log("init pagexy: " + this.initPageX + ", " + 
2829                                 //this.initPageY);
2830              //this.logger.log("last pagexy: " + this.lastPageX + ", " + 
2831                                 //this.lastPageY);
2832              // figure out how much this thing has moved
2833              var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
2834              var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
2835  
2836              this.setInitPosition(dx, dy);
2837  
2838          // This is the first time we have detected the element's position
2839          } else {
2840              this.setInitPosition();
2841          }
2842  
2843          if (this.constrainX) {
2844              this.setXConstraint( this.leftConstraint, 
2845                                   this.rightConstraint, 
2846                                   this.xTickSize        );
2847          }
2848  
2849          if (this.constrainY) {
2850              this.setYConstraint( this.topConstraint, 
2851                                   this.bottomConstraint, 
2852                                   this.yTickSize         );
2853          }
2854      },
2855  
2856      /**
2857       * Normally the drag element is moved pixel by pixel, but we can specify 
2858       * that it move a number of pixels at a time.  This method resolves the 
2859       * location when we have it set up like this.
2860       * @method getTick
2861       * @param {int} val where we want to place the object
2862       * @param {int[]} tickArray sorted array of valid points
2863       * @return {int} the closest tick
2864       * @private
2865       */
2866      getTick: function(val, tickArray) {
2867  
2868          if (!tickArray) {
2869              // If tick interval is not defined, it is effectively 1 pixel, 
2870              // so we return the value passed to us.
2871              return val; 
2872          } else if (tickArray[0] >= val) {
2873              // The value is lower than the first tick, so we return the first
2874              // tick.
2875              return tickArray[0];
2876          } else {
2877              for (var i=0, len=tickArray.length; i<len; ++i) {
2878                  var next = i + 1;
2879                  if (tickArray[next] && tickArray[next] >= val) {
2880                      var diff1 = val - tickArray[i];
2881                      var diff2 = tickArray[next] - val;
2882                      return (diff2 > diff1) ? tickArray[i] : tickArray[next];
2883                  }
2884              }
2885  
2886              // The value is larger than the last tick, so we return the last
2887              // tick.
2888              return tickArray[tickArray.length - 1];
2889          }
2890      },
2891  
2892      /**
2893       * toString method
2894       * @method toString
2895       * @return {string} string representation of the dd obj
2896       */
2897      toString: function() {
2898          return ("DragDrop " + this.id);
2899      }
2900  
2901  };
2902  YAHOO.augment(YAHOO.util.DragDrop, YAHOO.util.EventProvider);
2903  
2904  /**
2905  * @event mouseDownEvent
2906  * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
2907  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2908  */
2909  
2910  /**
2911  * @event b4MouseDownEvent
2912  * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
2913  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2914  */
2915  
2916  /**
2917  * @event mouseUpEvent
2918  * @description Fired from inside DragDropMgr when the drag operation is finished.
2919  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2920  */
2921  
2922  /**
2923  * @event b4StartDragEvent
2924  * @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
2925  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2926  */
2927  
2928  /**
2929  * @event startDragEvent
2930  * @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
2931  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2932  */
2933  
2934  /**
2935  * @event b4EndDragEvent
2936  * @description Fires before the endDragEvent. Returning false will cancel.
2937  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2938  */
2939  
2940  /**
2941  * @event endDragEvent
2942  * @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
2943  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2944  */
2945  
2946  /**
2947  * @event dragEvent
2948  * @description Occurs every mousemove event while dragging.
2949  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2950  */
2951  /**
2952  * @event b4DragEvent
2953  * @description Fires before the dragEvent.
2954  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2955  */
2956  /**
2957  * @event invalidDropEvent
2958  * @description Fires when the dragged objects is dropped in a location that contains no drop targets.
2959  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2960  */
2961  /**
2962  * @event b4DragOutEvent
2963  * @description Fires before the dragOutEvent
2964  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2965  */
2966  /**
2967  * @event dragOutEvent
2968  * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
2969  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2970  */
2971  /**
2972  * @event dragEnterEvent
2973  * @description Occurs when the dragged object first interacts with another targettable drag and drop object.
2974  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2975  */
2976  /**
2977  * @event b4DragOverEvent
2978  * @description Fires before the dragOverEvent.
2979  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2980  */
2981  /**
2982  * @event dragOverEvent
2983  * @description Fires every mousemove event while over a drag and drop object.
2984  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2985  */
2986  /**
2987  * @event b4DragDropEvent 
2988  * @description Fires before the dragDropEvent
2989  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2990  */
2991  /**
2992  * @event dragDropEvent
2993  * @description Fires when the dragged objects is dropped on another.
2994  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
2995  */
2996  })();
2997  /**
2998   * A DragDrop implementation where the linked element follows the 
2999   * mouse cursor during a drag.
3000   * @class DD
3001   * @extends YAHOO.util.DragDrop
3002   * @constructor
3003   * @param {String} id the id of the linked element 
3004   * @param {String} sGroup the group of related DragDrop items
3005   * @param {object} config an object containing configurable attributes
3006   *                Valid properties for DD: 
3007   *                    scroll
3008   */
3009  YAHOO.util.DD = function(id, sGroup, config) {
3010      if (id) {
3011          this.init(id, sGroup, config);
3012      }
3013  };
3014  
3015  YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, {
3016  
3017      /**
3018       * When set to true, the utility automatically tries to scroll the browser
3019       * window when a drag and drop element is dragged near the viewport boundary.
3020       * Defaults to true.
3021       * @property scroll
3022       * @type boolean
3023       */
3024      scroll: true, 
3025  
3026      /**
3027       * Sets the pointer offset to the distance between the linked element's top 
3028       * left corner and the location the element was clicked
3029       * @method autoOffset
3030       * @param {int} iPageX the X coordinate of the click
3031       * @param {int} iPageY the Y coordinate of the click
3032       */
3033      autoOffset: function(iPageX, iPageY) {
3034          var x = iPageX - this.startPageX;
3035          var y = iPageY - this.startPageY;
3036          this.setDelta(x, y);
3037          // this.logger.log("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y);
3038      },
3039  
3040      /** 
3041       * Sets the pointer offset.  You can call this directly to force the 
3042       * offset to be in a particular location (e.g., pass in 0,0 to set it 
3043       * to the center of the object, as done in YAHOO.widget.Slider)
3044       * @method setDelta
3045       * @param {int} iDeltaX the distance from the left
3046       * @param {int} iDeltaY the distance from the top
3047       */
3048      setDelta: function(iDeltaX, iDeltaY) {
3049          this.deltaX = iDeltaX;
3050          this.deltaY = iDeltaY;
3051          this.logger.log("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY);
3052      },
3053  
3054      /**
3055       * Sets the drag element to the location of the mousedown or click event, 
3056       * maintaining the cursor location relative to the location on the element 
3057       * that was clicked.  Override this if you want to place the element in a 
3058       * location other than where the cursor is.
3059       * @method setDragElPos
3060       * @param {int} iPageX the X coordinate of the mousedown or drag event
3061       * @param {int} iPageY the Y coordinate of the mousedown or drag event
3062       */
3063      setDragElPos: function(iPageX, iPageY) {
3064          // the first time we do this, we are going to check to make sure
3065          // the element has css positioning
3066  
3067          var el = this.getDragEl();
3068          this.alignElWithMouse(el, iPageX, iPageY);
3069      },
3070  
3071      /**
3072       * Sets the element to the location of the mousedown or click event, 
3073       * maintaining the cursor location relative to the location on the element 
3074       * that was clicked.  Override this if you want to place the element in a 
3075       * location other than where the cursor is.
3076       * @method alignElWithMouse
3077       * @param {HTMLElement} el the element to move
3078       * @param {int} iPageX the X coordinate of the mousedown or drag event
3079       * @param {int} iPageY the Y coordinate of the mousedown or drag event
3080       */
3081      alignElWithMouse: function(el, iPageX, iPageY) {
3082          var oCoord = this.getTargetCoord(iPageX, iPageY);
3083          // this.logger.log("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display);
3084  
3085          if (!this.deltaSetXY) {
3086              var aCoord = [oCoord.x, oCoord.y];
3087              YAHOO.util.Dom.setXY(el, aCoord);
3088  
3089              var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
3090              var newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
3091  
3092              this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
3093          } else {
3094              YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px");
3095              YAHOO.util.Dom.setStyle(el, "top",  (oCoord.y + this.deltaSetXY[1]) + "px");
3096          }
3097          
3098          this.cachePosition(oCoord.x, oCoord.y);
3099          var self = this;
3100          setTimeout(function() {
3101              self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
3102          }, 0);
3103      },
3104  
3105      /**
3106       * Saves the most recent position so that we can reset the constraints and
3107       * tick marks on-demand.  We need to know this so that we can calculate the
3108       * number of pixels the element is offset from its original position.
3109       * @method cachePosition
3110       * @param iPageX the current x position (optional, this just makes it so we
3111       * don't have to look it up again)
3112       * @param iPageY the current y position (optional, this just makes it so we
3113       * don't have to look it up again)
3114       */
3115      cachePosition: function(iPageX, iPageY) {
3116          if (iPageX) {
3117              this.lastPageX = iPageX;
3118              this.lastPageY = iPageY;
3119          } else {
3120              var aCoord = YAHOO.util.Dom.getXY(this.getEl());
3121              this.lastPageX = aCoord[0];
3122              this.lastPageY = aCoord[1];
3123          }
3124      },
3125  
3126      /**
3127       * Auto-scroll the window if the dragged object has been moved beyond the 
3128       * visible window boundary.
3129       * @method autoScroll
3130       * @param {int} x the drag element's x position
3131       * @param {int} y the drag element's y position
3132       * @param {int} h the height of the drag element
3133       * @param {int} w the width of the drag element
3134       * @private
3135       */
3136      autoScroll: function(x, y, h, w) {
3137  
3138          if (this.scroll) {
3139              // The client height
3140              var clientH = this.DDM.getClientHeight();
3141  
3142              // The client width
3143              var clientW = this.DDM.getClientWidth();
3144  
3145              // The amt scrolled down
3146              var st = this.DDM.getScrollTop();
3147  
3148              // The amt scrolled right
3149              var sl = this.DDM.getScrollLeft();
3150  
3151              // Location of the bottom of the element
3152              var bot = h + y;
3153  
3154              // Location of the right of the element
3155              var right = w + x;
3156  
3157              // The distance from the cursor to the bottom of the visible area, 
3158              // adjusted so that we don't scroll if the cursor is beyond the
3159              // element drag constraints
3160              var toBot = (clientH + st - y - this.deltaY);
3161  
3162              // The distance from the cursor to the right of the visible area
3163              var toRight = (clientW + sl - x - this.deltaX);
3164  
3165              // this.logger.log( " x: " + x + " y: " + y + " h: " + h + 
3166              // " clientH: " + clientH + " clientW: " + clientW + 
3167              // " st: " + st + " sl: " + sl + " bot: " + bot + 
3168              // " right: " + right + " toBot: " + toBot + " toRight: " + toRight);
3169  
3170              // How close to the edge the cursor must be before we scroll
3171              // var thresh = (document.all) ? 100 : 40;
3172              var thresh = 40;
3173  
3174              // How many pixels to scroll per autoscroll op.  This helps to reduce 
3175              // clunky scrolling. IE is more sensitive about this ... it needs this 
3176              // value to be higher.
3177              var scrAmt = (document.all) ? 80 : 30;
3178  
3179              // Scroll down if we are near the bottom of the visible page and the 
3180              // obj extends below the crease
3181              if ( bot > clientH && toBot < thresh ) { 
3182                  window.scrollTo(sl, st + scrAmt); 
3183              }
3184  
3185              // Scroll up if the window is scrolled down and the top of the object
3186              // goes above the top border
3187              if ( y < st && st > 0 && y - st < thresh ) { 
3188                  window.scrollTo(sl, st - scrAmt); 
3189              }
3190  
3191              // Scroll right if the obj is beyond the right border and the cursor is
3192              // near the border.
3193              if ( right > clientW && toRight < thresh ) { 
3194                  window.scrollTo(sl + scrAmt, st); 
3195              }
3196  
3197              // Scroll left if the window has been scrolled to the right and the obj
3198              // extends past the left border
3199              if ( x < sl && sl > 0 && x - sl < thresh ) { 
3200                  window.scrollTo(sl - scrAmt, st);
3201              }
3202          }
3203      },
3204  
3205      /*
3206       * Sets up config options specific to this class. Overrides
3207       * YAHOO.util.DragDrop, but all versions of this method through the 
3208       * inheritance chain are called
3209       */
3210      applyConfig: function() {
3211          YAHOO.util.DD.superclass.applyConfig.call(this);
3212          this.scroll = (this.config.scroll !== false);
3213      },
3214  
3215      /*
3216       * Event that fires prior to the onMouseDown event.  Overrides 
3217       * YAHOO.util.DragDrop.
3218       */
3219      b4MouseDown: function(e) {
3220          this.setStartPosition();
3221          // this.resetConstraints();
3222          this.autoOffset(YAHOO.util.Event.getPageX(e), 
3223                              YAHOO.util.Event.getPageY(e));
3224      },
3225  
3226      /*
3227       * Event that fires prior to the onDrag event.  Overrides 
3228       * YAHOO.util.DragDrop.
3229       */
3230      b4Drag: function(e) {
3231          this.setDragElPos(YAHOO.util.Event.getPageX(e), 
3232                              YAHOO.util.Event.getPageY(e));
3233      },
3234  
3235      toString: function() {
3236          return ("DD " + this.id);
3237      }
3238  
3239      //////////////////////////////////////////////////////////////////////////
3240      // Debugging ygDragDrop events that can be overridden
3241      //////////////////////////////////////////////////////////////////////////
3242      /*
3243      startDrag: function(x, y) {
3244          this.logger.log(this.id.toString()  + " startDrag");
3245      },
3246  
3247      onDrag: function(e) {
3248          this.logger.log(this.id.toString() + " onDrag");
3249      },
3250  
3251      onDragEnter: function(e, id) {
3252          this.logger.log(this.id.toString() + " onDragEnter: " + id);
3253      },
3254  
3255      onDragOver: function(e, id) {
3256          this.logger.log(this.id.toString() + " onDragOver: " + id);
3257      },
3258  
3259      onDragOut: function(e, id) {
3260          this.logger.log(this.id.toString() + " onDragOut: " + id);
3261      },
3262  
3263      onDragDrop: function(e, id) {
3264          this.logger.log(this.id.toString() + " onDragDrop: " + id);
3265      },
3266  
3267      endDrag: function(e) {
3268          this.logger.log(this.id.toString() + " endDrag");
3269      }
3270  
3271      */
3272  
3273  /**
3274  * @event mouseDownEvent
3275  * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3276  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3277  */
3278  
3279  /**
3280  * @event b4MouseDownEvent
3281  * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3282  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3283  */
3284  
3285  /**
3286  * @event mouseUpEvent
3287  * @description Fired from inside DragDropMgr when the drag operation is finished.
3288  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3289  */
3290  
3291  /**
3292  * @event b4StartDragEvent
3293  * @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3294  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3295  */
3296  
3297  /**
3298  * @event startDragEvent
3299  * @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3300  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3301  */
3302  
3303  /**
3304  * @event b4EndDragEvent
3305  * @description Fires before the endDragEvent. Returning false will cancel.
3306  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3307  */
3308  
3309  /**
3310  * @event endDragEvent
3311  * @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3312  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3313  */
3314  
3315  /**
3316  * @event dragEvent
3317  * @description Occurs every mousemove event while dragging.
3318  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3319  */
3320  /**
3321  * @event b4DragEvent
3322  * @description Fires before the dragEvent.
3323  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3324  */
3325  /**
3326  * @event invalidDropEvent
3327  * @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3328  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3329  */
3330  /**
3331  * @event b4DragOutEvent
3332  * @description Fires before the dragOutEvent
3333  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3334  */
3335  /**
3336  * @event dragOutEvent
3337  * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3338  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3339  */
3340  /**
3341  * @event dragEnterEvent
3342  * @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3343  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3344  */
3345  /**
3346  * @event b4DragOverEvent
3347  * @description Fires before the dragOverEvent.
3348  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3349  */
3350  /**
3351  * @event dragOverEvent
3352  * @description Fires every mousemove event while over a drag and drop object.
3353  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3354  */
3355  /**
3356  * @event b4DragDropEvent 
3357  * @description Fires before the dragDropEvent
3358  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3359  */
3360  /**
3361  * @event dragDropEvent
3362  * @description Fires when the dragged objects is dropped on another.
3363  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3364  */
3365  });
3366  /**
3367   * A DragDrop implementation that inserts an empty, bordered div into
3368   * the document that follows the cursor during drag operations.  At the time of
3369   * the click, the frame div is resized to the dimensions of the linked html
3370   * element, and moved to the exact location of the linked element.
3371   *
3372   * References to the "frame" element refer to the single proxy element that
3373   * was created to be dragged in place of all DDProxy elements on the
3374   * page.
3375   *
3376   * @class DDProxy
3377   * @extends YAHOO.util.DD
3378   * @constructor
3379   * @param {String} id the id of the linked html element
3380   * @param {String} sGroup the group of related DragDrop objects
3381   * @param {object} config an object containing configurable attributes
3382   *                Valid properties for DDProxy in addition to those in DragDrop: 
3383   *                   resizeFrame, centerFrame, dragElId
3384   */
3385  YAHOO.util.DDProxy = function(id, sGroup, config) {
3386      if (id) {
3387          this.init(id, sGroup, config);
3388          this.initFrame(); 
3389      }
3390  };
3391  
3392  /**
3393   * The default drag frame div id
3394   * @property YAHOO.util.DDProxy.dragElId
3395   * @type String
3396   * @static
3397   */
3398  YAHOO.util.DDProxy.dragElId = "ygddfdiv";
3399  
3400  YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, {
3401  
3402      /**
3403       * By default we resize the drag frame to be the same size as the element
3404       * we want to drag (this is to get the frame effect).  We can turn it off
3405       * if we want a different behavior.
3406       * @property resizeFrame
3407       * @type boolean
3408       */
3409      resizeFrame: true,
3410  
3411      /**
3412       * By default the frame is positioned exactly where the drag element is, so
3413       * we use the cursor offset provided by YAHOO.util.DD.  Another option that works only if
3414       * you do not have constraints on the obj is to have the drag frame centered
3415       * around the cursor.  Set centerFrame to true for this effect.
3416       * @property centerFrame
3417       * @type boolean
3418       */
3419      centerFrame: false,
3420  
3421      /**
3422       * Creates the proxy element if it does not yet exist
3423       * @method createFrame
3424       */
3425      createFrame: function() {
3426          var self=this, body=document.body;
3427  
3428          if (!body || !body.firstChild) {
3429              setTimeout( function() { self.createFrame(); }, 50 );
3430              return;
3431          }
3432  
3433          var div=this.getDragEl(), Dom=YAHOO.util.Dom;
3434  
3435          if (!div) {
3436              div    = document.createElement("div");
3437              div.id = this.dragElId;
3438              var s  = div.style;
3439  
3440              s.position   = "absolute";
3441              s.visibility = "hidden";
3442              s.cursor     = "move";
3443              s.border     = "2px solid #aaa";
3444              s.zIndex     = 999;
3445              s.height     = "25px";
3446              s.width      = "25px";
3447  
3448              var _data = document.createElement('div');
3449              Dom.setStyle(_data, 'height', '100%');
3450              Dom.setStyle(_data, 'width', '100%');
3451              /**
3452              * If the proxy element has no background-color, then it is considered to the "transparent" by Internet Explorer.
3453              * Since it is "transparent" then the events pass through it to the iframe below.
3454              * So creating a "fake" div inside the proxy element and giving it a background-color, then setting it to an
3455              * opacity of 0, it appears to not be there, however IE still thinks that it is so the events never pass through.
3456              */
3457              Dom.setStyle(_data, 'background-color', '#ccc');
3458              Dom.setStyle(_data, 'opacity', '0');
3459              div.appendChild(_data);
3460  
3461              // appendChild can blow up IE if invoked prior to the window load event
3462              // while rendering a table.  It is possible there are other scenarios 
3463              // that would cause this to happen as well.
3464              body.insertBefore(div, body.firstChild);
3465          }
3466      },
3467  
3468      /**
3469       * Initialization for the drag frame element.  Must be called in the
3470       * constructor of all subclasses
3471       * @method initFrame
3472       */
3473      initFrame: function() {
3474          this.createFrame();
3475      },
3476  
3477      applyConfig: function() {
3478          //this.logger.log("DDProxy applyConfig");
3479          YAHOO.util.DDProxy.superclass.applyConfig.call(this);
3480  
3481          this.resizeFrame = (this.config.resizeFrame !== false);
3482          this.centerFrame = (this.config.centerFrame);
3483          this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId);
3484      },
3485  
3486      /**
3487       * Resizes the drag frame to the dimensions of the clicked object, positions 
3488       * it over the object, and finally displays it
3489       * @method showFrame
3490       * @param {int} iPageX X click position
3491       * @param {int} iPageY Y click position
3492       * @private
3493       */
3494      showFrame: function(iPageX, iPageY) {
3495          var el = this.getEl();
3496          var dragEl = this.getDragEl();
3497          var s = dragEl.style;
3498  
3499          this._resizeProxy();
3500  
3501          if (this.centerFrame) {
3502              this.setDelta( Math.round(parseInt(s.width,  10)/2), 
3503                             Math.round(parseInt(s.height, 10)/2) );
3504          }
3505  
3506          this.setDragElPos(iPageX, iPageY);
3507  
3508          YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); 
3509      },
3510  
3511      /**
3512       * The proxy is automatically resized to the dimensions of the linked
3513       * element when a drag is initiated, unless resizeFrame is set to false
3514       * @method _resizeProxy
3515       * @private
3516       */
3517      _resizeProxy: function() {
3518          if (this.resizeFrame) {
3519              var DOM    = YAHOO.util.Dom;
3520              var el     = this.getEl();
3521              var dragEl = this.getDragEl();
3522  
3523              var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth"    ), 10);
3524              var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth"  ), 10);
3525              var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10);
3526              var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth"   ), 10);
3527  
3528              if (isNaN(bt)) { bt = 0; }
3529              if (isNaN(br)) { br = 0; }
3530              if (isNaN(bb)) { bb = 0; }
3531              if (isNaN(bl)) { bl = 0; }
3532  
3533              this.logger.log("proxy size: " + bt + "  " + br + " " + bb + " " + bl);
3534  
3535              var newWidth  = Math.max(0, el.offsetWidth  - br - bl);                                                                                           
3536              var newHeight = Math.max(0, el.offsetHeight - bt - bb);
3537  
3538              this.logger.log("Resizing proxy element");
3539  
3540              DOM.setStyle( dragEl, "width",  newWidth  + "px" );
3541              DOM.setStyle( dragEl, "height", newHeight + "px" );
3542          }
3543      },
3544  
3545      // overrides YAHOO.util.DragDrop
3546      b4MouseDown: function(e) {
3547          this.setStartPosition();
3548          var x = YAHOO.util.Event.getPageX(e);
3549          var y = YAHOO.util.Event.getPageY(e);
3550          this.autoOffset(x, y);
3551  
3552          // This causes the autoscroll code to kick off, which means autoscroll can
3553          // happen prior to the check for a valid drag handle.
3554          // this.setDragElPos(x, y);
3555      },
3556  
3557      // overrides YAHOO.util.DragDrop
3558      b4StartDrag: function(x, y) {
3559          // show the drag frame
3560          this.logger.log("start drag show frame, x: " + x + ", y: " + y);
3561          this.showFrame(x, y);
3562      },
3563  
3564      // overrides YAHOO.util.DragDrop
3565      b4EndDrag: function(e) {
3566          this.logger.log(this.id + " b4EndDrag");
3567          YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); 
3568      },
3569  
3570      // overrides YAHOO.util.DragDrop
3571      // By default we try to move the element to the last location of the frame.  
3572      // This is so that the default behavior mirrors that of YAHOO.util.DD.  
3573      endDrag: function(e) {
3574          var DOM = YAHOO.util.Dom;
3575          this.logger.log(this.id + " endDrag");
3576          var lel = this.getEl();
3577          var del = this.getDragEl();
3578  
3579          // Show the drag frame briefly so we can get its position
3580          // del.style.visibility = "";
3581          DOM.setStyle(del, "visibility", ""); 
3582  
3583          // Hide the linked element before the move to get around a Safari 
3584          // rendering bug.
3585          //lel.style.visibility = "hidden";
3586          DOM.setStyle(lel, "visibility", "hidden"); 
3587          YAHOO.util.DDM.moveToEl(lel, del);
3588          //del.style.visibility = "hidden";
3589          DOM.setStyle(del, "visibility", "hidden"); 
3590          //lel.style.visibility = "";
3591          DOM.setStyle(lel, "visibility", ""); 
3592      },
3593  
3594      toString: function() {
3595          return ("DDProxy " + this.id);
3596      }
3597  /**
3598  * @event mouseDownEvent
3599  * @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.
3600  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3601  */
3602  
3603  /**
3604  * @event b4MouseDownEvent
3605  * @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.
3606  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3607  */
3608  
3609  /**
3610  * @event mouseUpEvent
3611  * @description Fired from inside DragDropMgr when the drag operation is finished.
3612  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3613  */
3614  
3615  /**
3616  * @event b4StartDragEvent
3617  * @description Fires before the startDragEvent, returning false will cancel the startDrag Event.
3618  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3619  */
3620  
3621  /**
3622  * @event startDragEvent
3623  * @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. 
3624  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3625  */
3626  
3627  /**
3628  * @event b4EndDragEvent
3629  * @description Fires before the endDragEvent. Returning false will cancel.
3630  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3631  */
3632  
3633  /**
3634  * @event endDragEvent
3635  * @description Fires on the mouseup event after a drag has been initiated (startDrag fired).
3636  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3637  */
3638  
3639  /**
3640  * @event dragEvent
3641  * @description Occurs every mousemove event while dragging.
3642  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3643  */
3644  /**
3645  * @event b4DragEvent
3646  * @description Fires before the dragEvent.
3647  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3648  */
3649  /**
3650  * @event invalidDropEvent
3651  * @description Fires when the dragged objects is dropped in a location that contains no drop targets.
3652  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3653  */
3654  /**
3655  * @event b4DragOutEvent
3656  * @description Fires before the dragOutEvent
3657  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3658  */
3659  /**
3660  * @event dragOutEvent
3661  * @description Fires when a dragged object is no longer over an object that had the onDragEnter fire. 
3662  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3663  */
3664  /**
3665  * @event dragEnterEvent
3666  * @description Occurs when the dragged object first interacts with another targettable drag and drop object.
3667  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3668  */
3669  /**
3670  * @event b4DragOverEvent
3671  * @description Fires before the dragOverEvent.
3672  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3673  */
3674  /**
3675  * @event dragOverEvent
3676  * @description Fires every mousemove event while over a drag and drop object.
3677  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3678  */
3679  /**
3680  * @event b4DragDropEvent 
3681  * @description Fires before the dragDropEvent
3682  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3683  */
3684  /**
3685  * @event dragDropEvent
3686  * @description Fires when the dragged objects is dropped on another.
3687  * @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
3688  */
3689  
3690  });
3691  /**
3692   * A DragDrop implementation that does not move, but can be a drop 
3693   * target.  You would get the same result by simply omitting implementation 
3694   * for the event callbacks, but this way we reduce the processing cost of the 
3695   * event listener and the callbacks.
3696   * @class DDTarget
3697   * @extends YAHOO.util.DragDrop 
3698   * @constructor
3699   * @param {String} id the id of the element that is a drop target
3700   * @param {String} sGroup the group of related DragDrop objects
3701   * @param {object} config an object containing configurable attributes
3702   *                 Valid properties for DDTarget in addition to those in 
3703   *                 DragDrop: 
3704   *                    none
3705   */
3706  YAHOO.util.DDTarget = function(id, sGroup, config) {
3707      if (id) {
3708          this.initTarget(id, sGroup, config);
3709      }
3710  };
3711  
3712  // YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop();
3713  YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, {
3714      toString: function() {
3715          return ("DDTarget " + this.id);
3716      }
3717  });
3718  YAHOO.register("dragdrop", YAHOO.util.DragDropMgr, {version: "2.9.0", build: "2800"});
3719  
3720  }, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-event"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1