Index: openacs-4/packages/ajaxhelper/www/resources/yui/dragdrop/dragdrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/yui/dragdrop/dragdrop.js,v diff -u -r1.1 -r1.2 --- openacs-4/packages/ajaxhelper/www/resources/yui/dragdrop/dragdrop.js 21 Oct 2006 06:14:57 -0000 1.1 +++ openacs-4/packages/ajaxhelper/www/resources/yui/dragdrop/dragdrop.js 25 Dec 2006 16:40:02 -0000 1.2 @@ -1,23 +1,27 @@ -/* +/* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt -version: 0.11.3 -*/ +version: 0.12.1 +*/ +(function() { +var Event=YAHOO.util.Event; +var Dom=YAHOO.util.Dom; + /** - * Defines the interface and base operation of items that that can be + * Defines the interface and base operation of items that that can be * dragged or can be drop targets. It was designed to be extended, overriding * the event handlers for startDrag, onDrag, onDragOver, onDragOut. * Up to three html elements can be associated with a DragDrop instance: * * This class should not be instantiated until the onload event to ensure that * the associated elements are available. - * The following would define a DragDrop obj that would interact with any - * other * DragDrop obj in the "group1" group: + * The following would define a DragDrop obj that would interact with any + * other DragDrop obj in the "group1" group: *
  *  dd = new YAHOO.util.DragDrop("div1", "group1");
  * 
- * Since none of the event handlers have been implemented, nothing would - * actually happen if you were to run the code above. Normally you would - * override this class or one of the default implementations, but you can + * Since none of the event handlers have been implemented, nothing would + * actually happen if you were to run the code above. Normally you would + * override this class or one of the default implementations, but you can * also override the methods you want on an instance of the class... *
  *  dd.onDragDrop = function(e, id) {
- *   alert("dd was dropped on " + id);
+ *    alert("dd was dropped on " + id);
  *  }
  * 
+ * @namespace YAHOO.util + * @class DragDrop * @constructor * @param {String} id of the element that is linked to this instance * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes - * Valid properties for DragDrop: - * padding, isTarget, maintainOffset, primaryButtonOnly + * Valid properties for DragDrop: + * padding, isTarget, maintainOffset, primaryButtonOnly, */ YAHOO.util.DragDrop = function(id, sGroup, config) { if (id) { - this.init(id, sGroup, config); + this.init(id, sGroup, config); } }; YAHOO.util.DragDrop.prototype = { /** - * The id of the element associated with this object. This is what we - * refer to as the "linked element" because the size and position of - * this element is used to determine when the drag and drop objects have + * The id of the element associated with this object. This is what we + * refer to as the "linked element" because the size and position of + * this element is used to determine when the drag and drop objects have * interacted. - * + * @property id * @type String */ id: null, /** * Configuration attributes passed into the constructor + * @property config * @type object */ config: null, /** - * The id of the element that will be dragged. By default this is same - * as the linked element , but could be changed to another element. Ex: + * The id of the element that will be dragged. By default this is same + * as the linked element , but could be changed to another element. Ex: * YAHOO.util.DDProxy - * + * @property dragElId * @type String * @private */ - dragElId: null, + dragElId: null, /** - * the id of the element that initiates the drag operation. By default + * the id of the element that initiates the drag operation. By default * this is the linked element, but could be changed to be a child of this - * element. This lets us do things like only starting the drag when the + * element. This lets us do things like only starting the drag when the * header element within the linked html element is clicked. - * + * @property handleElId * @type String * @private */ - handleElId: null, + handleElId: null, /** * An associative array of HTML tags that will be ignored if clicked. + * @property invalidHandleTypes * @type {string: string} */ - invalidHandleTypes: null, + invalidHandleTypes: null, /** * An associative array of ids for elements that will be ignored if clicked + * @property invalidHandleIds * @type {string: string} */ - invalidHandleIds: null, + invalidHandleIds: null, /** * An indexted array of css class names for elements that will be ignored * if clicked. + * @property invalidHandleClasses * @type string[] */ - invalidHandleClasses: null, + invalidHandleClasses: null, /** - * The linked element's absolute X position at the time the drag was + * The linked element's absolute X position at the time the drag was * started - * + * @property startPageX * @type int * @private */ startPageX: 0, /** - * The linked element's absolute X position at the time the drag was + * The linked element's absolute X position at the time the drag was * started - * + * @property startPageY * @type int * @private */ startPageY: 0, /** - * The group defines a logical collection of DragDrop objects that are - * related. Instances only get events when interacting with other - * DragDrop object in the same group. This lets us define multiple + * The group defines a logical collection of DragDrop objects that are + * related. Instances only get events when interacting with other + * DragDrop object in the same group. This lets us define multiple * groups using a single DragDrop subclass if we want. + * @property groups * @type {string: string} */ groups: null, /** - * Individual drag/drop instances can be locked. This will prevent + * Individual drag/drop instances can be locked. This will prevent * onmousedown start drag. - * + * @property locked * @type boolean * @private */ locked: false, /** * Lock this instance + * @method lock */ lock: function() { this.locked = true; }, /** * Unlock this instace + * @method unlock */ unlock: function() { this.locked = false; }, /** * By default, all insances can be a drop target. This can be disabled by * setting isTarget to false. - * + * @method isTarget * @type boolean */ isTarget: true, /** * The padding configured for this drag and drop object for calculating * the drop zone intersection with this object. + * @method padding * @type int[] */ padding: null, /** + * Cached reference to the linked element + * @property _domRef * @private */ _domRef: null, /** * Internal typeof flag + * @property __ygDragDrop * @private */ __ygDragDrop: true, /** * Set to true when horizontal contraints are applied - * + * @property constrainX * @type boolean * @private */ constrainX: false, /** * Set to true when vertical contraints are applied - * + * @property constrainY * @type boolean * @private */ constrainY: false, /** * The left constraint - * + * @property minX * @type int * @private */ minX: 0, /** * The right constraint - * + * @property maxX * @type int * @private */ maxX: 0, /** - * The up constraint - * + * The up constraint + * @property minY * @type int + * @type int * @private */ minY: 0, /** - * The down constraint - * + * The down constraint + * @property maxY * @type int * @private */ maxY: 0, /** - * Maintain offsets when we resetconstraints. Used to maintain the - * slider thumb value, and this needs to be fixed. + * Maintain offsets when we resetconstraints. Set to true when you want + * the position of the element relative to its parent to stay the same + * when the page changes + * + * @property maintainOffset * @type boolean */ maintainOffset: false, /** - * Array of pixel locations the element will snap to if we specified a + * Array of pixel locations the element will snap to if we specified a * horizontal graduation/interval. This array is generated automatically * when you define a tick interval. + * @property xTicks * @type int[] */ xTicks: null, /** - * Array of pixel locations the element will snap to if we specified a - * vertical graduation/interval. This array is generated automatically + * Array of pixel locations the element will snap to if we specified a + * vertical graduation/interval. This array is generated automatically * when you define a tick interval. + * @property yTicks * @type int[] */ yTicks: null, @@ -260,208 +283,241 @@ * button click (left button for a right-handed mouse). Set to true to * allow drag and drop to start with any mouse click that is propogated * by the browser + * @property primaryButtonOnly * @type boolean */ primaryButtonOnly: true, /** * The availabe property is false until the linked dom element is accessible. + * @property available * @type boolean */ available: false, /** + * By default, drags can only be initiated if the mousedown occurs in the + * region the linked element is. This is done in part to work around a + * bug in some browsers that mis-report the mousedown if the previous + * mouseup happened outside of the window. This property is set to true + * if outer handles are defined. + * + * @property hasOuterHandles + * @type boolean + * @default false + */ + hasOuterHandles: false, + + /** * Code that executes immediately before the startDrag event + * @method b4StartDrag * @private */ b4StartDrag: function(x, y) { }, /** * Abstract method called after a drag/drop object is clicked * and the drag or mousedown time thresholds have beeen met. - * + * @method startDrag * @param {int} X click location * @param {int} Y click location */ startDrag: function(x, y) { /* override this */ }, /** * Code that executes immediately before the onDrag event + * @method b4Drag * @private */ b4Drag: function(e) { }, /** - * Abstract method called during the onMouseMove event while dragging an + * Abstract method called during the onMouseMove event while dragging an * object. - * - * @param {Event} e + * @method onDrag + * @param {Event} e the mousemove event */ onDrag: function(e) { /* override this */ }, /** - * Code that executes immediately before the onDragEnter event - * @private - */ - // b4DragEnter: function(e) { }, - - /** - * Abstract method called when this element fist begins hovering over + * Abstract method called when this element fist begins hovering over * another DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of one or more + * @method onDragEnter + * @param {Event} e the mousemove event + * @param {String|DragDrop[]} id In POINT mode, the element + * id this is hovering over. In INTERSECT mode, an array of one or more * dragdrop items being hovered over. */ onDragEnter: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragOver event + * @method b4DragOver * @private */ b4DragOver: function(e) { }, /** - * Abstract method called when this element is hovering over another + * Abstract method called when this element is hovering over another * DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of dd items + * @method onDragOver + * @param {Event} e the mousemove event + * @param {String|DragDrop[]} id In POINT mode, the element + * id this is hovering over. In INTERSECT mode, an array of dd items * being hovered over. */ onDragOver: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragOut event + * @method b4DragOut * @private */ b4DragOut: function(e) { }, /** * Abstract method called when we are no longer hovering over an element - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was hovering over. In INTERSECT mode, an array of dd items + * @method onDragOut + * @param {Event} e the mousemove event + * @param {String|DragDrop[]} id In POINT mode, the element + * id this was hovering over. In INTERSECT mode, an array of dd items * that the mouse is no longer over. */ onDragOut: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragDrop event + * @method b4DragDrop * @private */ b4DragDrop: function(e) { }, /** - * Abstract method called when this item is dropped on another DragDrop + * Abstract method called when this item is dropped on another DragDrop * obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was dropped on. In INTERSECT mode, an array of dd items this + * @method onDragDrop + * @param {Event} e the mouseup event + * @param {String|DragDrop[]} id In POINT mode, the element + * id this was dropped on. In INTERSECT mode, an array of dd items this * was dropped on. */ onDragDrop: function(e, id) { /* override this */ }, /** + * Abstract method called when this item is dropped on an area with no + * drop target + * @method onInvalidDrop + * @param {Event} e the mouseup event + */ + onInvalidDrop: function(e) { /* override this */ }, + + /** * Code that executes immediately before the endDrag event + * @method b4EndDrag * @private */ b4EndDrag: function(e) { }, /** * Fired when we are done dragging the object - * - * @param {Event} e + * @method endDrag + * @param {Event} e the mouseup event */ endDrag: function(e) { /* override this */ }, /** * Code executed immediately before the onMouseDown event - - * @param {Event} e + * @method b4MouseDown + * @param {Event} e the mousedown event * @private */ b4MouseDown: function(e) { }, /** * Event handler that fires when a drag/drop obj gets a mousedown - * @param {Event} e + * @method onMouseDown + * @param {Event} e the mousedown event */ onMouseDown: function(e) { /* override this */ }, /** * Event handler that fires when a drag/drop obj gets a mouseup - * @param {Event} e + * @method onMouseUp + * @param {Event} e the mouseup event */ onMouseUp: function(e) { /* override this */ }, - + /** * Override the onAvailable method to do what is needed after the initial * position was determined. + * @method onAvailable */ - onAvailable: function () { + onAvailable: function () { }, /** * Returns a reference to the linked element - * - * @return {HTMLElement} the html element + * @method getEl + * @return {HTMLElement} the html element */ - getEl: function() { + getEl: function() { if (!this._domRef) { - this._domRef = YAHOO.util.Dom.get(this.id); + this._domRef = Dom.get(this.id); } return this._domRef; }, /** * Returns a reference to the actual element to drag. By default this is - * the same as the html element, but it can be assigned to another + * the same as the html element, but it can be assigned to another * element. An example of this can be found in YAHOO.util.DDProxy - * - * @return {HTMLElement} the html element + * @method getDragEl + * @return {HTMLElement} the html element */ getDragEl: function() { - return YAHOO.util.Dom.get(this.dragElId); + return Dom.get(this.dragElId); }, /** * Sets up the DragDrop object. Must be called in the constructor of any * YAHOO.util.DragDrop subclass - * + * @method init * @param id the id of the linked element * @param {String} sGroup the group of related items * @param {object} config configuration attributes */ init: function(id, sGroup, config) { this.initTarget(id, sGroup, config); - YAHOO.util.Event.addListener(this.id, "mousedown", - this.handleMouseDown, this, true); + Event.on(this.id, "mousedown", this.handleMouseDown, this, true); + // Event.on(this.id, "selectstart", Event.preventDefault); }, /** * Initializes Targeting functionality only... the object does not * get a mousedown handler. - * + * @method initTarget * @param id the id of the linked element * @param {String} sGroup the group of related items * @param {object} config configuration attributes */ initTarget: function(id, sGroup, config) { - // configuration attributes + // configuration attributes this.config = config || {}; // create a local reference to the drag and drop manager this.DDM = YAHOO.util.DDM; // initialize the groups array this.groups = {}; + // assume that we have an element reference instead of an id if the + // parameter is not a string + if (typeof id !== "string") { + YAHOO.log("id is not a string, assuming it is an HTMLElement"); + id = Dom.generateId(id); + } + // set the id this.id = id; @@ -472,13 +528,13 @@ // so we just set the id rather than calling the setter. this.handleElId = id; - YAHOO.util.Event.onAvailable(id, this.handleOnAvailable, this, true); + Event.onAvailable(id, this.handleOnAvailable, this, true); // the linked element is the element that gets dragged by default - this.setDragElId(id); + this.setDragElId(id); - // by default, clicked anchors will not start drag operations. + // by default, clicked anchors will not start drag operations. // @TODO what else should be here? Probably form fields. this.invalidHandleTypes = { A: "A" }; this.invalidHandleIds = {}; @@ -490,13 +546,14 @@ /** * Applies the configuration parameters that were passed into the constructor. * This is supposed to happen at each level through the inheritance chain. So - * a DDProxy implentation will execute apply config on DDProxy, DD, and + * a DDProxy implentation will execute apply config on DDProxy, DD, and * DragDrop in order to get all of the parameters that are available in * each object. + * @method applyConfig */ applyConfig: function() { - // configurable properties: + // configurable properties: // padding, isTarget, maintainOffset, primaryButtonOnly this.padding = this.config.padding || [0, 0, 0, 0]; this.isTarget = (this.config.isTarget !== false); @@ -507,6 +564,7 @@ /** * Executed when the linked element is available + * @method handleOnAvailable * @private */ handleOnAvailable: function() { @@ -517,10 +575,11 @@ /** * Configures the padding for the target zone in px. Effectively expands - * (or reduces) the virtual object size for targeting calculations. + * (or reduces) the virtual object size for targeting calculations. * Supports css-style shorthand; if only one parameter is passed, all sides * will have that padding, and if only two are passed, the top and bottom * will have the first param, the left and right the second. + * @method setPadding * @param {int} iTop Top pad * @param {int} iRight Right pad * @param {int} iBot Bot pad @@ -538,7 +597,10 @@ }, /** - * Stores the initial placement of the dd element + * Stores the initial placement of the linked element. + * @method setInitialPosition + * @param {int} diffX the X offset, default 0 + * @param {int} diffY the Y offset, default 0 */ setInitPosition: function(diffX, diffY) { var el = this.getEl(); @@ -550,7 +612,7 @@ var dx = diffX || 0; var dy = diffY || 0; - var p = YAHOO.util.Dom.getXY( el ); + var p = Dom.getXY( el ); this.initPageX = p[0] - dx; this.initPageY = p[1] - dy; @@ -565,22 +627,24 @@ /** * Sets the start position of the element. This is set when the obj * is initialized, the reset when a drag is started. + * @method setStartPosition * @param pos current position (from previous lookup) * @private */ setStartPosition: function(pos) { - var p = pos || YAHOO.util.Dom.getXY( this.getEl() ); + var p = pos || Dom.getXY( this.getEl() ); + this.deltaSetXY = null; this.startPageX = p[0]; this.startPageY = p[1]; }, /** - * Add this instance to a group of related drag/drop objects. All - * instances belong to at least one group, and can belong to as many + * Add this instance to a group of related drag/drop objects. All + * instances belong to at least one group, and can belong to as many * groups as needed. - * + * @method addToGroup * @param sGroup {string} the name of the group */ addToGroup: function(sGroup) { @@ -590,6 +654,7 @@ /** * Remove's this instance from the supplied interaction group + * @method removeFromGroup * @param {string} sGroup The group to drop */ removeFromGroup: function(sGroup) { @@ -601,45 +666,59 @@ }, /** - * Allows you to specify that an element other than the linked element + * Allows you to specify that an element other than the linked element * will be moved with the cursor during a drag - * - * @param id the id of the element that will be used to initiate the drag + * @method setDragElId + * @param id {string} the id of the element that will be used to initiate the drag */ setDragElId: function(id) { this.dragElId = id; }, /** - * Allows you to specify a child of the linked element that should be - * used to initiate the drag operation. An example of this would be if - * you have a content div with text and links. Clicking anywhere in the + * Allows you to specify a child of the linked element that should be + * used to initiate the drag operation. An example of this would be if + * you have a content div with text and links. Clicking anywhere in the * content area would normally start the drag operation. Use this method - * to specify that an element inside of the content div is the element + * to specify that an element inside of the content div is the element * that starts the drag operation. - * - * @param id the id of the element that will be used to initiate the drag + * @method setHandleElId + * @param id {string} the id of the element that will be used to + * initiate the drag. */ setHandleElId: function(id) { + if (typeof id !== "string") { + YAHOO.log("id is not a string, assuming it is an HTMLElement"); + id = Dom.generateId(id); + } this.handleElId = id; this.DDM.regHandle(this.id, id); }, /** - * Allows you to set an element outside of the linked element as a drag + * Allows you to set an element outside of the linked element as a drag * handle + * @method setOuterHandleElId + * @param id the id of the element that will be used to initiate the drag */ setOuterHandleElId: function(id) { - YAHOO.util.Event.addListener(id, "mousedown", + if (typeof id !== "string") { + YAHOO.log("id is not a string, assuming it is an HTMLElement"); + id = Dom.generateId(id); + } + Event.on(id, "mousedown", this.handleMouseDown, this, true); this.setHandleElId(id); + + this.hasOuterHandles = true; }, /** * Remove all drag and drop hooks for this element + * @method unreg */ unreg: function() { - YAHOO.util.Event.removeListener(this.id, "mousedown", + Event.removeListener(this.id, "mousedown", this.handleMouseDown); this._domRef = null; this.DDM._remove(this); @@ -648,8 +727,8 @@ /** * Returns true if this instance is locked, or the drag drop mgr is locked * (meaning that all drag/drop is disabled on the page.) - * - * @return {boolean} true if this obj or all drag/drop is locked, else + * @method isLocked + * @return {boolean} true if this obj or all drag/drop is locked, else * false */ isLocked: function() { @@ -658,16 +737,13 @@ /** * Fired when this object is clicked - * - * @param {Event} e + * @method handleMouseDown + * @param {Event} e * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj) * @private */ handleMouseDown: function(e, oDD) { - - var EU = YAHOO.util.Event; - var button = e.which || e.button; if (this.primaryButtonOnly && button > 1) { @@ -682,24 +758,18 @@ // var self = this; // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0); - // Only process the event if we really clicked within the linked - // element. The reason we make this check is that in the case that - // another element was moved between the clicked element and the - // cursor in the time between the mousedown and mouseup events. When - // this happens, the element gets the next mousedown event - // regardless of where on the screen it happened. - var pt = new YAHOO.util.Point(EU.getPageX(e), EU.getPageY(e)); - if ( this.DDM.isOverTarget(pt, this) ) { + // Only process the event if we really clicked within the linked + // element. The reason we make this check is that in the case that + // another element was moved between the clicked element and the + // cursor in the time between the mousedown and mouseup events. When + // this happens, the element gets the next mousedown event + // regardless of where on the screen it happened. + var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e)); + if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { + } else { + if (this.clickValidator(e)) { - // check to see if the handle was clicked - var srcEl = EU.getTarget(e); - - if (this.isValidHandleChild(srcEl) && - (this.id == this.handleElId || - this.DDM.handleWasClicked(srcEl, this.id)) ) { - - // set the initial element position this.setStartPosition(); @@ -709,15 +779,25 @@ this.DDM.handleMouseDown(e, this); this.DDM.stopEvent(e); + } else { + + } } }, + clickValidator: function(e) { + var target = Event.getTarget(e); + return ( this.isValidHandleChild(target) && + (this.id == this.handleElId || + this.DDM.handleWasClicked(target, this.id)) ); + }, + /** * Allows you to specify a tag name that should not start a drag operation * when clicked. This is designed to facilitate embedding links within a * drag handle that do something other than start the drag. - * + * @method addInvalidHandleType * @param {string} tagName the type of element to exclude */ addInvalidHandleType: function(tagName) { @@ -728,14 +808,20 @@ /** * Lets you to specify an element id for a child of a drag handle * that should not initiate a drag + * @method addInvalidHandleId * @param {string} id the element id of the element you wish to ignore */ addInvalidHandleId: function(id) { + if (typeof id !== "string") { + YAHOO.log("id is not a string, assuming it is an HTMLElement"); + id = Dom.generateId(id); + } this.invalidHandleIds[id] = id; }, /** * Lets you specify a css class of elements that will not initiate a drag + * @method addInvalidHandleClass * @param {string} cssClass the class of the elements you wish to ignore */ addInvalidHandleClass: function(cssClass) { @@ -744,26 +830,33 @@ /** * Unsets an excluded tag name set by addInvalidHandleType - * + * @method removeInvalidHandleType * @param {string} tagName the type of element to unexclude */ removeInvalidHandleType: function(tagName) { var type = tagName.toUpperCase(); // this.invalidHandleTypes[type] = null; delete this.invalidHandleTypes[type]; }, - + /** * Unsets an invalid handle id - * @param {string} the id of the element to re-enable + * @method removeInvalidHandleId + * @param {string} id the id of the element to re-enable */ removeInvalidHandleId: function(id) { + if (typeof id !== "string") { + YAHOO.log("id is not a string, assuming it is an HTMLElement"); + id = Dom.generateId(id); + } delete this.invalidHandleIds[id]; }, /** * Unsets an invalid css class - * @param {string} the class of the element(s) you wish to re-enable + * @method removeInvalidHandleClass + * @param {string} cssClass the class of the element(s) you wish to + * re-enable */ removeInvalidHandleClass: function(cssClass) { for (var i=0, len=this.invalidHandleClasses.length; i= this.minX; i = i - iTickSize) { @@ -831,9 +924,9 @@ }, /** - * Create the array of vertical tick marks if an interval was specified in + * Create the array of vertical tick marks if an interval was specified in * setYConstraint(). - * + * @method setYTicks * @private */ setYTicks: function(iStartY, iTickSize) { @@ -860,14 +953,14 @@ }, /** - * By default, the element can be dragged any place on the screen. Use - * this method to limit the horizontal travel of the element. Pass in + * By default, the element can be dragged any place on the screen. Use + * this method to limit the horizontal travel of the element. Pass in * 0,0 for the parameters if you want to lock the drag to the y axis. - * + * @method setXConstraint * @param {int} iLeft the number of pixels the element can move to the left - * @param {int} iRight the number of pixels the element can move to the + * @param {int} iRight the number of pixels the element can move to the * right - * @param {int} iTickSize optional parameter for specifying that the + * @param {int} iTickSize optional parameter for specifying that the * element * should move iTickSize pixels at a time. */ @@ -885,6 +978,7 @@ /** * Clears any constraints applied to this instance. Also clears ticks * since they can't exist independent of a constraint at this time. + * @method clearConstraints */ clearConstraints: function() { this.constrainX = false; @@ -894,6 +988,7 @@ /** * Clears any tick interval defined for this instance + * @method clearTicks */ clearTicks: function() { this.xTicks = null; @@ -903,13 +998,13 @@ }, /** - * By default, the element can be dragged any place on the screen. Set + * By default, the element can be dragged any place on the screen. Set * this to limit the vertical travel of the element. Pass in 0,0 for the * parameters if you want to lock the drag to the x axis. - * + * @method setYConstraint * @param {int} iUp the number of pixels the element can move up * @param {int} iDown the number of pixels the element can move down - * @param {int} iTickSize optional parameter for specifying that the + * @param {int} iTickSize optional parameter for specifying that the * element should move iTickSize pixels at a time. */ setYConstraint: function(iUp, iDown, iTickSize) { @@ -921,11 +1016,12 @@ if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } this.constrainY = true; - + }, /** * resetConstraints must be called if you manually reposition a dd element. + * @method resetConstraints * @param {boolean} maintainOffset */ resetConstraints: function() { @@ -945,23 +1041,23 @@ } if (this.constrainX) { - this.setXConstraint( this.leftConstraint, - this.rightConstraint, + this.setXConstraint( this.leftConstraint, + this.rightConstraint, this.xTickSize ); } if (this.constrainY) { - this.setYConstraint( this.topConstraint, - this.bottomConstraint, + this.setYConstraint( this.topConstraint, + this.bottomConstraint, this.yTickSize ); } }, /** - * Normally the drag element is moved pixel by pixel, but we can specify - * that it move a number of pixels at a time. This method resolves the + * Normally the drag element is moved pixel by pixel, but we can specify + * that it move a number of pixels at a time. This method resolves the * location when we have it set up like this. - * + * @method getTick * @param {int} val where we want to place the object * @param {int[]} tickArray sorted array of valid points * @return {int} the closest tick @@ -970,9 +1066,9 @@ getTick: function(val, tickArray) { if (!tickArray) { - // If tick interval is not defined, it is effectively 1 pixel, + // If tick interval is not defined, it is effectively 1 pixel, // so we return the value passed to us. - return val; + return val; } else if (tickArray[0] >= val) { // The value is lower than the first tick, so we return the first // tick. @@ -995,6 +1091,7 @@ /** * toString method + * @method toString * @return {string} string representation of the dd obj */ toString: function() { @@ -1003,142 +1100,189 @@ }; -// Only load the library once. Rewriting the manager class would orphan +})(); +/** + * The drag and drop utility provides a framework for building drag and drop + * applications. In addition to enabling drag and drop for specific elements, + * the drag and drop elements are tracked by the manager class, and the + * interactions between the various elements are tracked during the drag and + * the implementing code is notified about these important moments. + * @module dragdrop + * @title Drag and Drop + * @requires yahoo,dom,event + * @namespace YAHOO.util + */ + +// Only load the library once. Rewriting the manager class would orphan // existing drag and drop instances. if (!YAHOO.util.DragDropMgr) { - /** - * Handles the element interaction for all DragDrop items in the - * window. Generally, you will not call this class directly, but it does - * have helper methods that could be useful in your DragDrop - * implementations. This class should not be instantiated; all methods - * are are static. - * - * @constructor - */ - YAHOO.util.DragDropMgr = new function() { +/** + * DragDropMgr is a singleton that tracks the element interaction for + * all DragDrop items in the window. Generally, you will not call + * this class directly, but it does have helper methods that could + * be useful in your DragDrop implementations. + * @class DragDropMgr + * @static + */ +YAHOO.util.DragDropMgr = function() { + var Event = YAHOO.util.Event; + + return { + /** - * Two dimensional Array of registered DragDrop objects. The first - * dimension is the DragDrop item group, the second the DragDrop + * Two dimensional Array of registered DragDrop objects. The first + * dimension is the DragDrop item group, the second the DragDrop * object. - * + * @property ids * @type {string: string} * @private + * @static */ - this.ids = {}; + ids: {}, /** - * Array of element ids defined as drag handles. Used to determine - * if the element that generated the mousedown event is actually the + * Array of element ids defined as drag handles. Used to determine + * if the element that generated the mousedown event is actually the * handle and not the html element itself. - * + * @property handleIds * @type {string: string} * @private + * @static */ - this.handleIds = {}; + handleIds: {}, /** * the DragDrop object that is currently being dragged - * + * @property dragCurrent * @type DragDrop * @private + * @static **/ - this.dragCurrent = null; + dragCurrent: null, /** * the DragDrop object(s) that are being hovered over - * + * @property dragOvers * @type Array * @private + * @static */ - this.dragOvers = {}; + dragOvers: {}, /** - * @private - */ - - /** * the X distance between the cursor and the object being dragged - * + * @property deltaX * @type int * @private + * @static */ - this.deltaX = 0; + deltaX: 0, /** * the Y distance between the cursor and the object being dragged - * + * @property deltaY * @type int * @private + * @static */ - this.deltaY = 0; + deltaY: 0, /** * Flag to determine if we should prevent the default behavior of the - * events we define. By default this is true, but this can be set to + * events we define. By default this is true, but this can be set to * false if you need the default behavior (not recommended) - * + * @property preventDefault * @type boolean + * @static */ - this.preventDefault = true; + preventDefault: true, /** - * Flag to determine if we should stop the propagation of the events + * Flag to determine if we should stop the propagation of the events * we generate. This is true by default but you may want to set it to * false if the html element contains other features that require the * mouse click. - * + * @property stopPropagation * @type boolean + * @static */ - this.stopPropagation = true; + stopPropagation: true, /** + * Internal flag that is set to true when drag and drop has been + * intialized + * @property initialized * @private + * @static */ - this.initalized = false; + initalized: false, /** * All drag and drop can be disabled. - * + * @property locked * @private + * @static */ - this.locked = false; + locked: false, /** * Called the first time an element is registered. - * + * @method init * @private + * @static */ - this.init = function() { + init: function() { this.initialized = true; - }; + }, /** - * In point mode, drag and drop interaction is defined by the + * In point mode, drag and drop interaction is defined by the * location of the cursor during the drag/drop + * @property POINT * @type int + * @static + * @final */ - this.POINT = 0; + POINT: 0, /** - * In intersect mode, drag and drop interactio nis defined by the + * In intersect mode, drag and drop interaction is defined by the + * cursor position or the amount of overlap of two or more drag and + * drop objects. + * @property INTERSECT + * @type int + * @static + * @final + */ + INTERSECT: 1, + + /** + * In intersect mode, drag and drop interaction is defined only by the * overlap of two or more drag and drop objects. + * @property STRICT_INTERSECT * @type int + * @static + * @final */ - this.INTERSECT = 1; + STRICT_INTERSECT: 2, /** - * The current drag and drop mode. Default it point mode + * The current drag and drop mode. Default: POINT + * @property mode * @type int + * @static */ - this.mode = this.POINT; + mode: 0, /** * Runs method on all drag and drop objects + * @method _execOnAll * @private + * @static */ - this._execOnAll = function(sMethod, args) { + _execOnAll: function(sMethod, args) { for (var i in this.ids) { for (var j in this.ids[i]) { var oDD = this.ids[i][j]; @@ -1148,134 +1292,159 @@ oDD[sMethod].apply(oDD, args); } } - }; + }, /** * Drag and drop initialization. Sets up the global event handlers + * @method _onLoad * @private + * @static */ - this._onLoad = function() { + _onLoad: function() { this.init(); - var EU = YAHOO.util.Event; + Event.on(document, "mouseup", this.handleMouseUp, this, true); + Event.on(document, "mousemove", this.handleMouseMove, this, true); + Event.on(window, "unload", this._onUnload, this, true); + Event.on(window, "resize", this._onResize, this, true); + // Event.on(window, "mouseout", this._test); - EU.on(document, "mouseup", this.handleMouseUp, this, true); - EU.on(document, "mousemove", this.handleMouseMove, this, true); - EU.on(window, "unload", this._onUnload, this, true); - EU.on(window, "resize", this._onResize, this, true); - // EU.on(window, "mouseout", this._test); + }, - }; - /** * Reset constraints on all drag and drop objs + * @method _onResize * @private + * @static */ - this._onResize = function(e) { + _onResize: function(e) { this._execOnAll("resetConstraints", []); - }; + }, /** * Lock all drag and drop functionality + * @method lock + * @static */ - this.lock = function() { this.locked = true; }; + lock: function() { this.locked = true; }, /** * Unlock all drag and drop functionality + * @method unlock + * @static */ - this.unlock = function() { this.locked = false; }; + unlock: function() { this.locked = false; }, /** * Is drag and drop locked? - * + * @method isLocked * @return {boolean} True if drag and drop is locked, false otherwise. + * @static */ - this.isLocked = function() { return this.locked; }; + isLocked: function() { return this.locked; }, /** * Location cache that is set for all drag drop objects when a drag is * initiated, cleared when the drag is finished. - * + * @property locationCache * @private + * @static */ - this.locationCache = {}; + locationCache: {}, /** * Set useCache to false if you want to force object the lookup of each * drag and drop linked element constantly during a drag. + * @property useCache * @type boolean + * @static */ - this.useCache = true; + useCache: true, /** - * The number of pixels that the mouse needs to move after the + * The number of pixels that the mouse needs to move after the * mousedown before the drag is initiated. Default=3; + * @property clickPixelThresh * @type int + * @static */ - this.clickPixelThresh = 3; + clickPixelThresh: 3, /** * The number of milliseconds after the mousedown event to initiate the * drag if we don't get a mouseup event. Default=1000 + * @property clickTimeThresh * @type int + * @static */ - this.clickTimeThresh = 1000; + clickTimeThresh: 1000, /** - * Flag that indicates that either the drag pixel threshold or the + * Flag that indicates that either the drag pixel threshold or the * mousdown time threshold has been met + * @property dragThreshMet * @type boolean * @private + * @static */ - this.dragThreshMet = false; + dragThreshMet: false, /** * Timeout used for the click time threshold + * @property clickTimeout * @type Object * @private + * @static */ - this.clickTimeout = null; + clickTimeout: null, /** - * The X position of the mousedown event stored for later use when a + * The X position of the mousedown event stored for later use when a * drag threshold is met. + * @property startX * @type int * @private + * @static */ - this.startX = 0; + startX: 0, /** - * The Y position of the mousedown event stored for later use when a + * The Y position of the mousedown event stored for later use when a * drag threshold is met. + * @property startY * @type int * @private + * @static */ - this.startY = 0; + startY: 0, /** - * Each DragDrop instance must be registered with the DragDropMgr. + * Each DragDrop instance must be registered with the DragDropMgr. * This is executed in DragDrop.init() - * + * @method regDragDrop * @param {DragDrop} oDD the DragDrop object to register * @param {String} sGroup the name of the group this element belongs to + * @static */ - this.regDragDrop = function(oDD, sGroup) { + regDragDrop: function(oDD, sGroup) { if (!this.initialized) { this.init(); } - + if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } this.ids[sGroup][oDD.id] = oDD; - }; + }, /** * Removes the supplied dd instance from the supplied group. Executed - * by DragDrop.removeFromGroup. + * by DragDrop.removeFromGroup, so don't call this function directly. + * @method removeDDFromGroup * @private + * @static */ - this.removeDDFromGroup = function(oDD, sGroup) { + removeDDFromGroup: function(oDD, sGroup) { if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } @@ -1284,58 +1453,63 @@ if (obj && obj[oDD.id]) { delete obj[oDD.id]; } - }; + }, /** - * Unregisters a drag and drop item. This is executed in + * Unregisters a drag and drop item. This is executed in * DragDrop.unreg, use that method instead of calling this directly. + * @method _remove * @private + * @static */ - this._remove = function(oDD) { + _remove: function(oDD) { for (var g in oDD.groups) { if (g && this.ids[g][oDD.id]) { delete this.ids[g][oDD.id]; } } delete this.handleIds[oDD.id]; - }; + }, /** * Each DragDrop handle element must be registered. This is done * automatically when executing DragDrop.setHandleElId() - * + * @method regHandle * @param {String} sDDId the DragDrop id this element is a handle for - * @param {String} sHandleId the id of the element that is the drag + * @param {String} sHandleId the id of the element that is the drag * handle + * @static */ - this.regHandle = function(sDDId, sHandleId) { + regHandle: function(sDDId, sHandleId) { if (!this.handleIds[sDDId]) { this.handleIds[sDDId] = {}; } this.handleIds[sDDId][sHandleId] = sHandleId; - }; + }, /** - * Utility function to determine if a given element has been + * Utility function to determine if a given element has been * registered as a drag drop item. - * + * @method isDragDrop * @param {String} id the element id to check - * @return {boolean} true if this element is a DragDrop item, + * @return {boolean} true if this element is a DragDrop item, * false otherwise + * @static */ - this.isDragDrop = function(id) { + isDragDrop: function(id) { return ( this.getDDById(id) ) ? true : false; - }; + }, /** * Returns the drag and drop instances that are in all groups the * passed in instance belongs to. - * + * @method getRelated * @param {DragDrop} p_oDD the obj to get related data for * @param {boolean} bTargetsOnly if true, only return targetable objs * @return {DragDrop[]} the related instances + * @static */ - this.getRelated = function(p_oDD, bTargetsOnly) { + getRelated: function(p_oDD, bTargetsOnly) { var oDDs = []; for (var i in p_oDD.groups) { for (j in this.ids[i]) { @@ -1350,18 +1524,19 @@ } return oDDs; - }; + }, /** - * Returns true if the specified dd target is a legal target for + * Returns true if the specified dd target is a legal target for * the specifice drag obj - * + * @method isLegalTarget * @param {DragDrop} the drag obj - * @param {DragDrop) the target - * @return {boolean} true if the target is a legal target for the + * @param {DragDrop} the target + * @return {boolean} true if the target is a legal target for the * dd obj + * @static */ - this.isLegalTarget = function (oDD, oTargetDD) { + isLegalTarget: function (oDD, oTargetDD) { var targets = this.getRelated(oDD, true); for (var i=0, len=targets.length;i this.clickPixelThresh || + if (diffX > this.clickPixelThresh || diffY > this.clickPixelThresh) { this.startDrag(this.startX, this.startY); } @@ -1571,20 +1755,21 @@ this.stopEvent(e); return true; - }; + }, /** - * Iterates over all of the DragDrop elements to find ones we are + * Iterates over all of the DragDrop elements to find ones we are * hovering over or dropping on - * + * @method fireEvents * @param {Event} e the event * @param {boolean} isDrop is this a drop op or a mouseover op? * @private + * @static */ - this.fireEvents = function(e, isDrop) { + fireEvents: function(e, isDrop) { var dc = this.dragCurrent; - // If the user did the mouse up outside of the window, we could + // If the user did the mouse up outside of the window, we could // get here even though we have ended the drag. if (!dc || dc.isLocked()) { return; @@ -1602,7 +1787,7 @@ var dropEvts = []; var enterEvts = []; - // Check to see if the object(s) we were hovering over is no longer + // Check to see if the object(s) we were hovering over is no longer // being hovered over so we can fire the onDragOut event for (var i in this.dragOvers) { @@ -1621,7 +1806,7 @@ } for (var sGroup in dc.groups) { - + if ("string" != typeof sGroup) { continue; } @@ -1682,13 +1867,13 @@ dc.b4DragOut(e, outEvts[i].id); dc.onDragOut(e, outEvts[i].id); } - + // fire enter events for (i=0,len=enterEvts.length; i * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups); - * + * * Alternatively: - * + * * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true}); - * + * * @TODO this really should be an indexed array. Alternatively this * method could accept both. - * + * @method refreshCache * @param {Object} groups an associative array of groups to refresh + * @static */ - this.refreshCache = function(groups) { - for (sGroup in groups) { + refreshCache: function(groups) { + for (var sGroup in groups) { if ("string" != typeof sGroup) { continue; } - for (i in this.ids[sGroup]) { + for (var i in this.ids[sGroup]) { var oDD = this.ids[sGroup][i]; if (this.isTypeOfDD(oDD)) { @@ -1790,17 +1977,19 @@ } } } - }; + }, /** * This checks to make sure an element exists and is in the DOM. The * main purpose is to handle cases where innerHTML is used to remove * drag and drop objects from the DOM. IE provides an 'unspecified * error' when trying to access the offsetParent of such an element + * @method verifyEl * @param {HTMLElement} el the element to check * @return {boolean} true if the element looks usable + * @static */ - this.verifyEl = function(el) { + verifyEl: function(el) { try { if (el) { var parent = el.offsetParent; @@ -1812,65 +2001,57 @@ } return false; - }; - + }, + /** - * Returns the an array containing the drag and drop element's position - * and size, including the DragDrop.padding configured for it - * - * @param {DragDrop} oDD the drag and drop object to get the - * location for - * @return array containing the top left and bottom right points of the - * element + * Returns a Region object containing the drag and drop element's position + * and size, including the padding configured for it + * @method getLocation + * @param {DragDrop} oDD the drag and drop object to get the + * location for + * @return {YAHOO.util.Region} a Region object representing the total area + * the element occupies, including any padding + * the instance is configured for. + * @static */ - this.getLocation = function(oDD) { + getLocation: function(oDD) { if (! this.isTypeOfDD(oDD)) { return null; } - var el = oDD.getEl(); + var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l; - // element will not have an offsetparent if it was removed from the - // document or display=none - // if (!this.verifyEl(el)) { - // return null; - // } - - - // var aPos = ygPos.getPos(el); - var aPos = null; try { - aPos= YAHOO.util.Dom.getXY(el); + pos= YAHOO.util.Dom.getXY(el); } catch (e) { } - if (!aPos) { + if (!pos) { return null; } - x1 = aPos[0]; + x1 = pos[0]; x2 = x1 + el.offsetWidth; - - y1 = aPos[1]; + y1 = pos[1]; y2 = y1 + el.offsetHeight; - var t = y1 - oDD.padding[0]; - var r = x2 + oDD.padding[1]; - var b = y2 + oDD.padding[2]; - var l = x1 - oDD.padding[3]; + t = y1 - oDD.padding[0]; + r = x2 + oDD.padding[1]; + b = y2 + oDD.padding[2]; + l = x1 - oDD.padding[3]; return new YAHOO.util.Region( t, r, b, l ); + }, - }; - /** * Checks the cursor location to see if it over the target - * + * @method isOverTarget * @param {YAHOO.util.Point} pt The point to evaluate * @param {DragDrop} oTarget the DragDrop object we are inspecting * @return {boolean} true if the mouse is over the target * @private + * @static */ - this.isOverTarget = function(pt, oTarget, intersect) { + isOverTarget: function(pt, oTarget, intersect) { // use cache if available var loc = this.locationCache[oTarget.id]; if (!loc || !this.useCache) { @@ -1887,11 +2068,11 @@ // DragDrop is using this as a sanity check for the initial mousedown // in this case we are done. In POINT mode, if the drag obj has no - // contraints, we are also done. Otherwise we need to evaluate the + // contraints, we are also done. Otherwise we need to evaluate the // location of the target as related to the actual location of the // dragged element. var dc = this.dragCurrent; - if (!dc || !dc.getTargetCoord || + if (!dc || !dc.getTargetCoord || (!intersect && !dc.constrainX && !dc.constrainY)) { return oTarget.cursorIsOver; } @@ -1905,9 +2086,9 @@ var pos = dc.getTargetCoord(pt.x, pt.y); var el = dc.getDragEl(); - var curRegion = new YAHOO.util.Region( pos.y, + var curRegion = new YAHOO.util.Region( pos.y, pos.x + el.offsetWidth, - pos.y + el.offsetHeight, + pos.y + el.offsetHeight, pos.x ); var overlap = curRegion.intersect(loc); @@ -1918,20 +2099,25 @@ } else { return false; } - }; + }, /** + * unload event handler + * @method _onUnload * @private + * @static */ - this._onUnload = function(e, me) { + _onUnload: function(e, me) { this.unregAll(); - }; + }, /** * Cleans up the drag and drop events and objects. + * @method unregAll * @private + * @static */ - this.unregAll = function() { + unregAll: function() { if (this.dragCurrent) { this.stopDrag(); @@ -1946,218 +2132,266 @@ this.elementCache = {}; this.ids = {}; - }; + }, /** * A cache of DOM elements + * @property elementCache * @private + * @static */ - this.elementCache = {}; - + elementCache: {}, + /** * Get the wrapper for the DOM element specified - * - * @param {String} id the id of the elment to get + * @method getElWrapper + * @param {String} id the id of the element to get * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element * @private - * @deprecated + * @deprecated This wrapper isn't that useful + * @static */ - this.getElWrapper = function(id) { + getElWrapper: function(id) { var oWrapper = this.elementCache[id]; if (!oWrapper || !oWrapper.el) { - oWrapper = this.elementCache[id] = + oWrapper = this.elementCache[id] = new this.ElementWrapper(YAHOO.util.Dom.get(id)); } return oWrapper; - }; + }, /** * Returns the actual DOM element - * + * @method getElement * @param {String} id the id of the elment to get * @return {Object} The element - * @deprecated + * @deprecated use YAHOO.util.Dom.get instead + * @static */ - this.getElement = function(id) { + getElement: function(id) { return YAHOO.util.Dom.get(id); - }; - + }, + /** - * Returns the style property for the DOM element (i.e., + * Returns the style property for the DOM element (i.e., * document.getElById(id).style) - * + * @method getCss * @param {String} id the id of the elment to get * @return {Object} The style property of the element - * @deprecated + * @deprecated use YAHOO.util.Dom instead + * @static */ - this.getCss = function(id) { + getCss: function(id) { var el = YAHOO.util.Dom.get(id); return (el) ? el.style : null; - }; + }, /** * Inner class for cached elements + * @class DragDropMgr.ElementWrapper + * @for DragDropMgr * @private * @deprecated */ - this.ElementWrapper = function(el) { + ElementWrapper: function(el) { /** - * @private + * The element + * @property el */ this.el = el || null; /** - * @private + * The element id + * @property id */ this.id = this.el && el.id; /** - * @private + * A reference to the style property + * @property css */ this.css = this.el && el.style; - }; + }, /** * Returns the X position of an html element + * @method getPosX * @param el the element for which to get the position * @return {int} the X coordinate - * @deprecated + * @for DragDropMgr + * @deprecated use YAHOO.util.Dom.getX instead + * @static */ - this.getPosX = function(el) { + getPosX: function(el) { return YAHOO.util.Dom.getX(el); - }; + }, /** * Returns the Y position of an html element + * @method getPosY * @param el the element for which to get the position * @return {int} the Y coordinate - * @deprecated + * @deprecated use YAHOO.util.Dom.getY instead + * @static */ - this.getPosY = function(el) { - return YAHOO.util.Dom.getY(el); - }; + getPosY: function(el) { + return YAHOO.util.Dom.getY(el); + }, /** - * Swap two nodes. In IE, we use the native method, for others we + * Swap two nodes. In IE, we use the native method, for others we * emulate the IE behavior - * + * @method swapNode * @param n1 the first node to swap * @param n2 the other node to swap + * @static */ - this.swapNode = function(n1, n2) { + swapNode: function(n1, n2) { if (n1.swapNode) { n1.swapNode(n2); } else { - // the node reference order for the swap is a little tricky. var p = n2.parentNode; var s = n2.nextSibling; - n1.parentNode.replaceChild(n2, n1); - p.insertBefore(n1,s); + + if (s == n1) { + p.insertBefore(n1, n2); + } else if (n2 == n1.nextSibling) { + p.insertBefore(n2, n1); + } else { + n1.parentNode.replaceChild(n2, n1); + p.insertBefore(n1, s); + } } - }; + }, /** + * Returns the current scroll position + * @method getScroll * @private + * @static */ - this.getScroll = function () { - var t, l; - if (document.documentElement && document.documentElement.scrollTop) { - t = document.documentElement.scrollTop; - l = document.documentElement.scrollLeft; - } else if (document.body) { - t = document.body.scrollTop; - l = document.body.scrollLeft; + getScroll: function () { + var t, l, dde=document.documentElement, db=document.body; + if (dde && (dde.scrollTop || dde.scrollLeft)) { + t = dde.scrollTop; + l = dde.scrollLeft; + } else if (db) { + t = db.scrollTop; + l = db.scrollLeft; + } else { + YAHOO.log("could not get scroll property"); } return { top: t, left: l }; - }; + }, /** * Returns the specified element style property + * @method getStyle * @param {HTMLElement} el the element * @param {string} styleProp the style property * @return {string} The value of the style property - * @deprecated, use YAHOO.util.Dom.getStyle + * @deprecated use YAHOO.util.Dom.getStyle + * @static */ - this.getStyle = function(el, styleProp) { + getStyle: function(el, styleProp) { return YAHOO.util.Dom.getStyle(el, styleProp); - }; + }, /** * Gets the scrollTop + * @method getScrollTop * @return {int} the document's scrollTop + * @static */ - this.getScrollTop = function () { return this.getScroll().top; }; + getScrollTop: function () { return this.getScroll().top; }, /** * Gets the scrollLeft + * @method getScrollLeft * @return {int} the document's scrollTop + * @static */ - this.getScrollLeft = function () { return this.getScroll().left; }; + getScrollLeft: function () { return this.getScroll().left; }, /** * Sets the x/y position of an element to the location of the * target element. + * @method moveToEl * @param {HTMLElement} moveEl The element to move * @param {HTMLElement} targetEl The position reference element + * @static */ - this.moveToEl = function (moveEl, targetEl) { + moveToEl: function (moveEl, targetEl) { var aCoord = YAHOO.util.Dom.getXY(targetEl); YAHOO.util.Dom.setXY(moveEl, aCoord); - }; + }, /** * Gets the client height + * @method getClientHeight * @return {int} client height in px - * @deprecated + * @deprecated use YAHOO.util.Dom.getViewportHeight instead + * @static */ - this.getClientHeight = function() { - return YAHOO.util.Dom.getClientHeight(); - }; + getClientHeight: function() { + return YAHOO.util.Dom.getViewportHeight(); + }, /** * Gets the client width + * @method getClientWidth * @return {int} client width in px - * @deprecated + * @deprecated use YAHOO.util.Dom.getViewportWidth instead + * @static */ - this.getClientWidth = function() { - return YAHOO.util.Dom.getClientWidth(); - }; + getClientWidth: function() { + return YAHOO.util.Dom.getViewportWidth(); + }, /** - * numeric array sort function + * Numeric array sort function + * @method numericSort + * @static */ - this.numericSort = function(a, b) { return (a - b); }; + numericSort: function(a, b) { return (a - b); }, /** + * Internal counter + * @property _timeoutCount * @private + * @static */ - this._timeoutCount = 0; + _timeoutCount: 0, /** * Trying to make the load order less important. Without this we get * an error if this file is loaded before the Event Utility. + * @method _addListeners * @private + * @static */ - this._addListeners = function() { + _addListeners: function() { + var DDM = YAHOO.util.DDM; if ( YAHOO.util.Event && document ) { - this._onLoad(); + DDM._onLoad(); } else { - if (this._timeoutCount > 1000) { + if (DDM._timeoutCount > 2000) { } else { - var DDM = YAHOO.util.DDM; - setTimeout( function() { DDM._addListeners(); }, 10); + setTimeout(DDM._addListeners, 10); if (document && document.body) { - this._timeoutCount += 1; + DDM._timeoutCount += 1; } } } - }; + }, /** - * Recursively searches the immediate parent and all child nodes for - * the handle element in order to determine wheter or not it was + * Recursively searches the immediate parent and all child nodes for + * the handle element in order to determine wheter or not it was * clicked. + * @method handleWasClicked * @param node the html element to inspect + * @static */ - this.handleWasClicked = function(node, id) { + handleWasClicked: function(node, id) { if (this.isHandle(id, node.id)) { return true; } else { @@ -2174,32 +2408,28 @@ } return false; - }; + } - } (); + }; - // shorter alias, save a few bytes - YAHOO.util.DDM = YAHOO.util.DragDropMgr; - YAHOO.util.DDM._addListeners(); +}(); +// shorter alias, save a few bytes +YAHOO.util.DDM = YAHOO.util.DragDropMgr; +YAHOO.util.DDM._addListeners(); + } -//YAHOO.util.DragDropMgr.enableWindow = function(win) { - //var EU = YAHOO.util.Event; - //EU.on(win.document, "mouseup", this.handleMouseUp, this, true); - //EU.on(win.document, "mousemove", this.handleMouseMove, this, true); -//}; - /** - * A DragDrop implementation where the linked element follows the + * A DragDrop implementation where the linked element follows the * mouse cursor during a drag. - * + * @class DD * @extends YAHOO.util.DragDrop * @constructor - * @param {String} id the id of the linked element + * @param {String} id the id of the linked element * @param {String} sGroup the group of related DragDrop items * @param {object} config an object containing configurable attributes - * Valid properties for DD: + * Valid properties for DD: * scroll */ YAHOO.util.DD = function(id, sGroup, config) { @@ -2208,281 +2438,278 @@ } }; -// YAHOO.util.DD.prototype = new YAHOO.util.DragDrop(); -YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop); +YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, { -/** - * When set to true, the utility automatically tries to scroll the browser - * window wehn a drag and drop element is dragged near the viewport boundary. - * Defaults to true. - * - * @type boolean - */ -YAHOO.util.DD.prototype.scroll = true; + /** + * When set to true, the utility automatically tries to scroll the browser + * window wehn a drag and drop element is dragged near the viewport boundary. + * Defaults to true. + * @property scroll + * @type boolean + */ + scroll: true, -/** - * Sets the pointer offset to the distance between the linked element's top - * left corner and the location the element was clicked - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - */ -YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) { - // var el = this.getEl(); - // var aCoord = YAHOO.util.Dom.getXY(el); - // var x = iPageX - aCoord[0]; - // var y = iPageY - aCoord[1]; - var x = iPageX - this.startPageX; - var y = iPageY - this.startPageY; - this.setDelta(x, y); -}; + /** + * Sets the pointer offset to the distance between the linked element's top + * left corner and the location the element was clicked + * @method autoOffset + * @param {int} iPageX the X coordinate of the click + * @param {int} iPageY the Y coordinate of the click + */ + autoOffset: function(iPageX, iPageY) { + var x = iPageX - this.startPageX; + var y = iPageY - this.startPageY; + this.setDelta(x, y); + }, -/** - * Sets the pointer offset. You can call this directly to force the offset to - * be in a particular location (e.g., pass in 0,0 to set it to the center of the - * object, as done in YAHOO.widget.Slider) - * - * @param {int} iDeltaX the distance from the left - * @param {int} iDeltaY the distance from the top - */ -YAHOO.util.DD.prototype.setDelta = function(iDeltaX, iDeltaY) { - this.deltaX = iDeltaX; - this.deltaY = iDeltaY; -}; + /** + * Sets the pointer offset. You can call this directly to force the + * offset to be in a particular location (e.g., pass in 0,0 to set it + * to the center of the object, as done in YAHOO.widget.Slider) + * @method setDelta + * @param {int} iDeltaX the distance from the left + * @param {int} iDeltaY the distance from the top + */ + setDelta: function(iDeltaX, iDeltaY) { + this.deltaX = iDeltaX; + this.deltaY = iDeltaY; + }, -/** - * Sets the drag element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ + /** + * Sets the drag element to the location of the mousedown or click event, + * maintaining the cursor location relative to the location on the element + * that was clicked. Override this if you want to place the element in a + * location other than where the cursor is. + * @method setDragElPos + * @param {int} iPageX the X coordinate of the mousedown or drag event + * @param {int} iPageY the Y coordinate of the mousedown or drag event + */ + setDragElPos: function(iPageX, iPageY) { + // the first time we do this, we are going to check to make sure + // the element has css positioning -YAHOO.util.DD.prototype.setDragElPos = function(iPageX, iPageY) { - // the first time we do this, we are going to check to make sure - // the element has css positioning + var el = this.getDragEl(); + this.alignElWithMouse(el, iPageX, iPageY); + }, - var el = this.getDragEl(); + /** + * Sets the element to the location of the mousedown or click event, + * maintaining the cursor location relative to the location on the element + * that was clicked. Override this if you want to place the element in a + * location other than where the cursor is. + * @method alignElWithMouse + * @param {HTMLElement} el the element to move + * @param {int} iPageX the X coordinate of the mousedown or drag event + * @param {int} iPageY the Y coordinate of the mousedown or drag event + */ + alignElWithMouse: function(el, iPageX, iPageY) { + var oCoord = this.getTargetCoord(iPageX, iPageY); - // if (!this.cssVerified) { - // var pos = el.style.position; - // } + if (!this.deltaSetXY) { + var aCoord = [oCoord.x, oCoord.y]; + YAHOO.util.Dom.setXY(el, aCoord); + var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); + var newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); - this.alignElWithMouse(el, iPageX, iPageY); -}; + this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ]; + } else { + YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px"); + YAHOO.util.Dom.setStyle(el, "top", (oCoord.y + this.deltaSetXY[1]) + "px"); + } + + this.cachePosition(oCoord.x, oCoord.y); + this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); + }, -/** - * Sets the element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {HTMLElement} el the element to move - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ -YAHOO.util.DD.prototype.alignElWithMouse = function(el, iPageX, iPageY) { - var oCoord = this.getTargetCoord(iPageX, iPageY); + /** + * Saves the most recent position so that we can reset the constraints and + * tick marks on-demand. We need to know this so that we can calculate the + * number of pixels the element is offset from its original position. + * @method cachePosition + * @param iPageX the current x position (optional, this just makes it so we + * don't have to look it up again) + * @param iPageY the current y position (optional, this just makes it so we + * don't have to look it up again) + */ + cachePosition: function(iPageX, iPageY) { + if (iPageX) { + this.lastPageX = iPageX; + this.lastPageY = iPageY; + } else { + var aCoord = YAHOO.util.Dom.getXY(this.getEl()); + this.lastPageX = aCoord[0]; + this.lastPageY = aCoord[1]; + } + }, - // this.deltaSetXY = null; - if (!this.deltaSetXY) { - var aCoord = [oCoord.x, oCoord.y]; - YAHOO.util.Dom.setXY(el, aCoord); - var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); - var newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); + /** + * Auto-scroll the window if the dragged object has been moved beyond the + * visible window boundary. + * @method autoScroll + * @param {int} x the drag element's x position + * @param {int} y the drag element's y position + * @param {int} h the height of the drag element + * @param {int} w the width of the drag element + * @private + */ + autoScroll: function(x, y, h, w) { - this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ]; + if (this.scroll) { + // The client height + var clientH = this.DDM.getClientHeight(); - } else { - YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px"); - YAHOO.util.Dom.setStyle(el, "top", (oCoord.y + this.deltaSetXY[1]) + "px"); - } + // The client width + var clientW = this.DDM.getClientWidth(); + // The amt scrolled down + var st = this.DDM.getScrollTop(); - this.cachePosition(oCoord.x, oCoord.y); + // The amt scrolled right + var sl = this.DDM.getScrollLeft(); - this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); -}; + // Location of the bottom of the element + var bot = h + y; -/** - * Saves the most recent position so that we can reset the constraints and - * tick marks on-demand. We need to know this so that we can calculate the - * number of pixels the element is offset from its original position. - */ -YAHOO.util.DD.prototype.cachePosition = function(iPageX, iPageY) { - if (iPageX) { - this.lastPageX = iPageX; - this.lastPageY = iPageY; - } else { - var aCoord = YAHOO.util.Dom.getXY(this.getEl()); - this.lastPageX = aCoord[0]; - this.lastPageY = aCoord[1]; - } -}; + // Location of the right of the element + var right = w + x; -/** - * Auto-scroll the window if the dragged object has been moved beyond the - * visible window boundary. - * - * @param {int} x the drag element's x position - * @param {int} y the drag element's y position - * @param {int} h the height of the drag element - * @param {int} w the width of the drag element - * @private - */ -YAHOO.util.DD.prototype.autoScroll = function(x, y, h, w) { + // The distance from the cursor to the bottom of the visible area, + // adjusted so that we don't scroll if the cursor is beyond the + // element drag constraints + var toBot = (clientH + st - y - this.deltaY); - if (this.scroll) { - // The client height - var clientH = this.DDM.getClientHeight(); + // The distance from the cursor to the right of the visible area + var toRight = (clientW + sl - x - this.deltaX); - // The client width - var clientW = this.DDM.getClientWidth(); - // The amt scrolled down - var st = this.DDM.getScrollTop(); + // How close to the edge the cursor must be before we scroll + // var thresh = (document.all) ? 100 : 40; + var thresh = 40; - // The amt scrolled right - var sl = this.DDM.getScrollLeft(); + // How many pixels to scroll per autoscroll op. This helps to reduce + // clunky scrolling. IE is more sensitive about this ... it needs this + // value to be higher. + var scrAmt = (document.all) ? 80 : 30; - // Location of the bottom of the element - var bot = h + y; + // Scroll down if we are near the bottom of the visible page and the + // obj extends below the crease + if ( bot > clientH && toBot < thresh ) { + window.scrollTo(sl, st + scrAmt); + } - // Location of the right of the element - var right = w + x; + // Scroll up if the window is scrolled down and the top of the object + // goes above the top border + if ( y < st && st > 0 && y - st < thresh ) { + window.scrollTo(sl, st - scrAmt); + } - // The distance from the cursor to the bottom of the visible area, - // adjusted so that we don't scroll if the cursor is beyond the - // element drag constraints - var toBot = (clientH + st - y - this.deltaY); + // Scroll right if the obj is beyond the right border and the cursor is + // near the border. + if ( right > clientW && toRight < thresh ) { + window.scrollTo(sl + scrAmt, st); + } - // The distance from the cursor to the right of the visible area - var toRight = (clientW + sl - x - this.deltaX); + // Scroll left if the window has been scrolled to the right and the obj + // extends past the left border + if ( x < sl && sl > 0 && x - sl < thresh ) { + window.scrollTo(sl - scrAmt, st); + } + } + }, + /** + * Finds the location the element should be placed if we want to move + * it to where the mouse location less the click offset would place us. + * @method getTargetCoord + * @param {int} iPageX the X coordinate of the click + * @param {int} iPageY the Y coordinate of the click + * @return an object that contains the coordinates (Object.x and Object.y) + * @private + */ + getTargetCoord: function(iPageX, iPageY) { - // How close to the edge the cursor must be before we scroll - // var thresh = (document.all) ? 100 : 40; - var thresh = 40; - // How many pixels to scroll per autoscroll op. This helps to reduce - // clunky scrolling. IE is more sensitive about this ... it needs this - // value to be higher. - var scrAmt = (document.all) ? 80 : 30; + var x = iPageX - this.deltaX; + var y = iPageY - this.deltaY; - // Scroll down if we are near the bottom of the visible page and the - // obj extends below the crease - if ( bot > clientH && toBot < thresh ) { - window.scrollTo(sl, st + scrAmt); + if (this.constrainX) { + if (x < this.minX) { x = this.minX; } + if (x > this.maxX) { x = this.maxX; } } - // Scroll up if the window is scrolled down and the top of the object - // goes above the top border - if ( y < st && st > 0 && y - st < thresh ) { - window.scrollTo(sl, st - scrAmt); + if (this.constrainY) { + if (y < this.minY) { y = this.minY; } + if (y > this.maxY) { y = this.maxY; } } - // Scroll right if the obj is beyond the right border and the cursor is - // near the border. - if ( right > clientW && toRight < thresh ) { - window.scrollTo(sl + scrAmt, st); - } + x = this.getTick(x, this.xTicks); + y = this.getTick(y, this.yTicks); - // Scroll left if the window has been scrolled to the right and the obj - // extends past the left border - if ( x < sl && sl > 0 && x - sl < thresh ) { - window.scrollTo(sl - scrAmt, st); - } - } -}; -/** - * Finds the location the element should be placed if we want to move - * it to where the mouse location less the click offset would place us. - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - * @return an object that contains the coordinates (Object.x and Object.y) - * @private - */ -YAHOO.util.DD.prototype.getTargetCoord = function(iPageX, iPageY) { + return {x:x, y:y}; + }, + /* + * Sets up config options specific to this class. Overrides + * YAHOO.util.DragDrop, but all versions of this method through the + * inheritance chain are called + */ + applyConfig: function() { + YAHOO.util.DD.superclass.applyConfig.call(this); + this.scroll = (this.config.scroll !== false); + }, - var x = iPageX - this.deltaX; - var y = iPageY - this.deltaY; + /* + * Event that fires prior to the onMouseDown event. Overrides + * YAHOO.util.DragDrop. + */ + b4MouseDown: function(e) { + // this.resetConstraints(); + this.autoOffset(YAHOO.util.Event.getPageX(e), + YAHOO.util.Event.getPageY(e)); + }, - if (this.constrainX) { - if (x < this.minX) { x = this.minX; } - if (x > this.maxX) { x = this.maxX; } - } + /* + * Event that fires prior to the onDrag event. Overrides + * YAHOO.util.DragDrop. + */ + b4Drag: function(e) { + this.setDragElPos(YAHOO.util.Event.getPageX(e), + YAHOO.util.Event.getPageY(e)); + }, - if (this.constrainY) { - if (y < this.minY) { y = this.minY; } - if (y > this.maxY) { y = this.maxY; } + toString: function() { + return ("DD " + this.id); } - x = this.getTick(x, this.xTicks); - y = this.getTick(y, this.yTicks); + ////////////////////////////////////////////////////////////////////////// + // Debugging ygDragDrop events that can be overridden + ////////////////////////////////////////////////////////////////////////// + /* + startDrag: function(x, y) { + }, + onDrag: function(e) { + }, - return {x:x, y:y}; -}; + onDragEnter: function(e, id) { + }, -YAHOO.util.DD.prototype.applyConfig = function() { - YAHOO.util.DD.superclass.applyConfig.call(this); - this.scroll = (this.config.scroll !== false); -}; + onDragOver: function(e, id) { + }, -/** - * Event that fires prior to the onMouseDown event. Overrides - * YAHOO.util.DragDrop. - */ -YAHOO.util.DD.prototype.b4MouseDown = function(e) { - // this.resetConstraints(); - this.autoOffset(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; + onDragOut: function(e, id) { + }, -/** - * Event that fires prior to the onDrag event. Overrides - * YAHOO.util.DragDrop. - */ -YAHOO.util.DD.prototype.b4Drag = function(e) { - this.setDragElPos(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; + onDragDrop: function(e, id) { + }, -YAHOO.util.DD.prototype.toString = function() { - return ("DD " + this.id); -}; + endDrag: function(e) { + } -/////////////////////////////////////////////////////////////////////////////// -// Debugging ygDragDrop events that can be overridden -/////////////////////////////////////////////////////////////////////////////// -/* -YAHOO.util.DD.prototype.startDrag = function(x, y) { -}; + */ -YAHOO.util.DD.prototype.onDrag = function(e) { -}; - -YAHOO.util.DD.prototype.onDragEnter = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragOver = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragOut = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragDrop = function(e, id) { -}; - -YAHOO.util.DD.prototype.endDrag = function(e) { -}; -*/ - +}); /** * A DragDrop implementation that inserts an empty, bordered div into * the document that follows the cursor during drag operations. At the time of @@ -2493,223 +2720,229 @@ * was created to be dragged in place of all DDProxy elements on the * page. * + * @class DDProxy * @extends YAHOO.util.DD * @constructor * @param {String} id the id of the linked html element * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes - * Valid properties for DDProxy in addition to those in DragDrop: + * Valid properties for DDProxy in addition to those in DragDrop: * resizeFrame, centerFrame, dragElId */ YAHOO.util.DDProxy = function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); - this.initFrame(); + this.initFrame(); } }; -YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD); - /** * The default drag frame div id + * @property YAHOO.util.DDProxy.dragElId * @type String + * @static */ YAHOO.util.DDProxy.dragElId = "ygddfdiv"; -/** - * By default we resize the drag frame to be the same size as the element - * we want to drag (this is to get the frame effect). We can turn it off - * if we want a different behavior. - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.resizeFrame = true; +YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, { -/** - * By default the frame is positioned exactly where the drag element is, so - * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if - * you do not have constraints on the obj is to have the drag frame centered - * around the cursor. Set centerFrame to true for this effect. - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.centerFrame = false; + /** + * By default we resize the drag frame to be the same size as the element + * we want to drag (this is to get the frame effect). We can turn it off + * if we want a different behavior. + * @property resizeFrame + * @type boolean + */ + resizeFrame: true, -/** - * Create the drag frame if needed - */ -YAHOO.util.DDProxy.prototype.createFrame = function() { - var self = this; - var body = document.body; + /** + * By default the frame is positioned exactly where the drag element is, so + * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if + * you do not have constraints on the obj is to have the drag frame centered + * around the cursor. Set centerFrame to true for this effect. + * @property centerFrame + * @type boolean + */ + centerFrame: false, - if (!body || !body.firstChild) { - setTimeout( function() { self.createFrame(); }, 50 ); - return; - } + /** + * Creates the proxy element if it does not yet exist + * @method createFrame + */ + createFrame: function() { + var self = this; + var body = document.body; - var div = this.getDragEl(); + if (!body || !body.firstChild) { + setTimeout( function() { self.createFrame(); }, 50 ); + return; + } - if (!div) { - div = document.createElement("div"); - div.id = this.dragElId; - var s = div.style; + var div = this.getDragEl(); - s.position = "absolute"; - s.visibility = "hidden"; - s.cursor = "move"; - s.border = "2px solid #aaa"; - s.zIndex = 999; + if (!div) { + div = document.createElement("div"); + div.id = this.dragElId; + var s = div.style; - // appendChild can blow up IE if invoked prior to the window load event - // while rendering a table. It is possible there are other scenarios - // that would cause this to happen as well. - body.insertBefore(div, body.firstChild); - } -}; + s.position = "absolute"; + s.visibility = "hidden"; + s.cursor = "move"; + s.border = "2px solid #aaa"; + s.zIndex = 999; -/** - * Initialization for the drag frame element. Must be called in the - * constructor of all subclasses - */ -YAHOO.util.DDProxy.prototype.initFrame = function() { - // YAHOO.util.DDProxy.createFrame(); - // this.setDragElId(YAHOO.util.DDProxy.dragElId); + // appendChild can blow up IE if invoked prior to the window load event + // while rendering a table. It is possible there are other scenarios + // that would cause this to happen as well. + body.insertBefore(div, body.firstChild); + } + }, - this.createFrame(); + /** + * Initialization for the drag frame element. Must be called in the + * constructor of all subclasses + * @method initFrame + */ + initFrame: function() { + this.createFrame(); + }, -}; + applyConfig: function() { + YAHOO.util.DDProxy.superclass.applyConfig.call(this); -YAHOO.util.DDProxy.prototype.applyConfig = function() { - YAHOO.util.DDProxy.superclass.applyConfig.call(this); + this.resizeFrame = (this.config.resizeFrame !== false); + this.centerFrame = (this.config.centerFrame); + this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId); + }, - this.resizeFrame = (this.config.resizeFrame !== false); - this.centerFrame = (this.config.centerFrame); - this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId); + /** + * Resizes the drag frame to the dimensions of the clicked object, positions + * it over the object, and finally displays it + * @method showFrame + * @param {int} iPageX X click position + * @param {int} iPageY Y click position + * @private + */ + showFrame: function(iPageX, iPageY) { + var el = this.getEl(); + var dragEl = this.getDragEl(); + var s = dragEl.style; -}; + this._resizeProxy(); -/** - * Resizes the drag frame to the dimensions of the clicked object, positions - * it over the object, and finally displays it - * - * @param {int} iPageX X click position - * @param {int} iPageY Y click position - * @private - */ -YAHOO.util.DDProxy.prototype.showFrame = function(iPageX, iPageY) { - var el = this.getEl(); - var dragEl = this.getDragEl(); - var s = dragEl.style; + if (this.centerFrame) { + this.setDelta( Math.round(parseInt(s.width, 10)/2), + Math.round(parseInt(s.height, 10)/2) ); + } - this._resizeProxy(); + this.setDragElPos(iPageX, iPageY); - if (this.centerFrame) { - this.setDelta( Math.round(parseInt(s.width, 10)/2), - Math.round(parseInt(s.height, 10)/2) ); - } + YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); + }, - this.setDragElPos(iPageX, iPageY); + /** + * The proxy is automatically resized to the dimensions of the linked + * element when a drag is initiated, unless resizeFrame is set to false + * @method _resizeProxy + * @private + */ + _resizeProxy: function() { + if (this.resizeFrame) { + var DOM = YAHOO.util.Dom; + var el = this.getEl(); + var dragEl = this.getDragEl(); - YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); -}; + var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth" ), 10); + var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth" ), 10); + var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10); + var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth" ), 10); -YAHOO.util.DDProxy.prototype._resizeProxy = function() { - if (this.resizeFrame) { - var DOM = YAHOO.util.Dom; - var el = this.getEl(); - var dragEl = this.getDragEl(); + if (isNaN(bt)) { bt = 0; } + if (isNaN(br)) { br = 0; } + if (isNaN(bb)) { bb = 0; } + if (isNaN(bl)) { bl = 0; } - var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth" ), 10); - var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth" ), 10); - var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10); - var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth" ), 10); - if (isNaN(bt)) { bt = 0; } - if (isNaN(br)) { br = 0; } - if (isNaN(bb)) { bb = 0; } - if (isNaN(bl)) { bl = 0; } + var newWidth = Math.max(0, el.offsetWidth - br - bl); + var newHeight = Math.max(0, el.offsetHeight - bt - bb); - var newWidth = Math.max(0, el.offsetWidth - br - bl); - var newHeight = Math.max(0, el.offsetHeight - bt - bb); + DOM.setStyle( dragEl, "width", newWidth + "px" ); + DOM.setStyle( dragEl, "height", newHeight + "px" ); + } + }, + // overrides YAHOO.util.DragDrop + b4MouseDown: function(e) { + var x = YAHOO.util.Event.getPageX(e); + var y = YAHOO.util.Event.getPageY(e); + this.autoOffset(x, y); + this.setDragElPos(x, y); + }, - DOM.setStyle( dragEl, "width", newWidth + "px" ); - DOM.setStyle( dragEl, "height", newHeight + "px" ); - } -}; + // overrides YAHOO.util.DragDrop + b4StartDrag: function(x, y) { + // show the drag frame + this.showFrame(x, y); + }, -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4MouseDown = function(e) { - var x = YAHOO.util.Event.getPageX(e); - var y = YAHOO.util.Event.getPageY(e); - this.autoOffset(x, y); - this.setDragElPos(x, y); -}; + // overrides YAHOO.util.DragDrop + b4EndDrag: function(e) { + YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); + }, -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4StartDrag = function(x, y) { - // show the drag frame - this.showFrame(x, y); -}; + // overrides YAHOO.util.DragDrop + // By default we try to move the element to the last location of the frame. + // This is so that the default behavior mirrors that of YAHOO.util.DD. + endDrag: function(e) { + var DOM = YAHOO.util.Dom; + var lel = this.getEl(); + var del = this.getDragEl(); -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4EndDrag = function(e) { - YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); -}; + // Show the drag frame briefly so we can get its position + // del.style.visibility = ""; + DOM.setStyle(del, "visibility", ""); -// overrides YAHOO.util.DragDrop -// By default we try to move the element to the last location of the frame. -// This is so that the default behavior mirrors that of YAHOO.util.DD. -YAHOO.util.DDProxy.prototype.endDrag = function(e) { - var DOM = YAHOO.util.Dom; - var lel = this.getEl(); - var del = this.getDragEl(); + // Hide the linked element before the move to get around a Safari + // rendering bug. + //lel.style.visibility = "hidden"; + DOM.setStyle(lel, "visibility", "hidden"); + YAHOO.util.DDM.moveToEl(lel, del); + //del.style.visibility = "hidden"; + DOM.setStyle(del, "visibility", "hidden"); + //lel.style.visibility = ""; + DOM.setStyle(lel, "visibility", ""); + }, - // Show the drag frame briefly so we can get its position - // del.style.visibility = ""; - DOM.setStyle(del, "visibility", ""); + toString: function() { + return ("DDProxy " + this.id); + } - // Hide the linked element before the move to get around a Safari - // rendering bug. - //lel.style.visibility = "hidden"; - DOM.setStyle(lel, "visibility", "hidden"); - YAHOO.util.DDM.moveToEl(lel, del); - //del.style.visibility = "hidden"; - DOM.setStyle(del, "visibility", "hidden"); - //lel.style.visibility = ""; - DOM.setStyle(lel, "visibility", ""); -}; - -YAHOO.util.DDProxy.prototype.toString = function() { - return ("DDProxy " + this.id); -}; - +}); /** - * A DragDrop implementation that does not move, but can be a drop - * target. You would get the same result by simply omitting implementation - * for the event callbacks, but this way we reduce the processing cost of the + * A DragDrop implementation that does not move, but can be a drop + * target. You would get the same result by simply omitting implementation + * for the event callbacks, but this way we reduce the processing cost of the * event listener and the callbacks. - * - * @extends YAHOO.util.DragDrop + * @class DDTarget + * @extends YAHOO.util.DragDrop * @constructor * @param {String} id the id of the element that is a drop target * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes - * Valid properties for DDTarget in addition to those in DragDrop: - * none + * Valid properties for DDTarget in addition to those in + * DragDrop: + * none */ - YAHOO.util.DDTarget = function(id, sGroup, config) { if (id) { this.initTarget(id, sGroup, config); } }; // YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop(); -YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop); - -YAHOO.util.DDTarget.prototype.toString = function() { - return ("DDTarget " + this.id); -}; - +YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, { + toString: function() { + return ("DDTarget " + this.id); + } +});