/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. version 0.9.0 */ /** * @class 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: *
* 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
* also override the methods you want on an instance of the class...
*
* dd.onDragDrop = function(e, id) {
* alert("dd was dropped on " + id);
* }
*
* @constructor
* @param {String} id of the element that is linked to this instance
* @param {String} sGroup the group of related DragDrop objects
*/
YAHOO.util.DragDrop = function(id, sGroup) {
if (id) {
this.init(id, sGroup);
}
};
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
* interacted.
*
* @type String
*/
id: 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:
* YAHOO.util.DDProxy
*
* @type String
* @private
*/
dragElId: null,
/**
* 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
* header element within the linked html element is clicked.
*
* @type String
* @private
*/
handleElId: null,
/**
* An array of HTML tags that will be ignored if clicked.
*/
invalidHandleTypes: null,
/**
* The linked element's absolute X position at the time the drag was
* started
*
* @type int
* @private
*/
startPageX: 0,
/**
* The linked element's absolute X position at the time the drag was
* started
*
* @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
* groups using a single DragDrop subclass if we want.
*
*/
groups: null,
/**
* Individual drag/drop instances can be locked. This will prevent
* onmousedown start drag.
*
* @type boolean
* @private
*/
locked: false,
/**
* Lock this instance
*/
lock: function() { this.locked = true; },
/**
* Unlock this instace
*/
unlock: function() { this.locked = false; },
/**
* By default, all insances can be a drop target. This can be disabled by
* setting isTarget to false.
*
* @type boolean
*/
isTarget: true,
/**
* The padding configured for this drag and drop object for calculating
* the drop zone intersection with this object.
*/
padding: null,
/**
* @private
*/
_domRef: null,
/**
* Internal typeof flag
* @private
*/
__ygDragDrop: true,
/**
* Set to true when horizontal contraints are applied
*
* @type boolean
* @private
*/
constrainX: false,
/**
* Set to true when vertical contraints are applied
*
* @type boolean
* @private
*/
constrainY: false,
/**
* The left constraint
*
* @type int
* @private
*/
minX: 0,
/**
* The right constraint
*
* @type int
* @private
*/
maxX: 0,
/**
* The up constraint
*
* @type int
* @private
*/
minY: 0,
/**
* The down constraint
*
* @type int
* @private
*/
maxY: 0,
/**
* Maintain offsets when we resetconstraints. Used to maintain the
* slider thumb value, and this needs to be fixed.
* @type boolean
*/
maintainOffset: false,
/**
* 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.
* @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
* when you define a tick interval.
* @type int[]
*/
yTicks: null,
/**
* By default the drag and drop instance will only respond to the primary
* 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
* @type boolean
*/
primaryButtonOnly: true,
/**
* Code that executes immediately before the startDrag event
* @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.
*
* @param {int} X click location
* @param {int} Y click location
*/
startDrag: function(x, y) { /* override this */ },
/**
* Code that executes immediately before the onDrag event
* @private
*/
b4Drag: function(e) { },
/**
* Abstract method called during the onMouseMove event while dragging an
* object.
*
* @param {Event} e
*/
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
* 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
* dragdrop items being hovered over.
*/
onDragEnter: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragOver event
* @private
*/
b4DragOver: function(e) { },
/**
* 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
* being hovered over.
*/
onDragOver: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragOut event
* @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
* that the mouse is no longer over.
*/
onDragOut: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragDrop event
* @private
*/
b4DragDrop: function(e) { },
/**
* 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
* was dropped on.
*/
onDragDrop: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the endDrag event
* @private
*/
b4EndDrag: function(e) { },
/**
* Fired when we are done dragging the object
*
* @param {Event} e
*/
endDrag: function(e) { /* override this */ },
/**
* Code executed immediately before the onMouseDown event
* @param {Event} e
* @private
*/
b4MouseDown: function(e) { },
/**
* Event handler that fires when a drag/drop obj gets a mousedown
* @param {Event} e
*/
onMouseDown: function(e) { /* override this */ },
/**
* Event handler that fires when a drag/drop obj gets a mouseup
* @param {Event} e
*/
onMouseUp: function(e) { /* override this */ },
/**
* Returns a reference to the linked element
*
* @return {Object} the html element
*/
getEl: function() {
if (!this._domRef) {
this._domRef = this.DDM.getElement(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
* element. An example of this can be found in YAHOO.util.DDProxy
*
* @return {Object} the html element
*/
getDragEl: function() {
return this.DDM.getElement(this.dragElId);
},
/**
* Sets up the DragDrop object. Must be called in the constructor of any
* YAHOO.util.DragDrop subclass
*
* @param id the id of the linked element
* @param {String} sGroup the group of related items
* element is supposed to be a target only, set to false.
*/
init: function(id, sGroup) {
this.initTarget(id, sGroup);
YAHOO.util.Event.addListener(id, "mousedown",
this.handleMouseDown, this, true);
},
/**
* Initializes Targeting functionality only... the object does not
* get a mousedown handler.
*
* @param id the id of the linked element
* @param {String} sGroup the group of related items
* element is supposed to be a target only, set to false.
*/
initTarget: function(id, sGroup) {
// create a local reference to the drag and drop manager
this.DDM = YAHOO.util.DDM;
// create a logger instance
this.logger = new ygLogger("DragDrop");
// set the default padding
this.padding = [0, 0, 0, 0];
// initialize the groups array
this.groups = {};
// set the id
this.id = id;
// the element is a drag handle by default
this.setDragElId(id);
// by default, clicked anchors will not start drag operations
this.invalidHandleTypes = {a : "a"};
// We don't want to register this as the handle with the manager
// so we just set the id rather than calling the setter
this.handleElId = id;
// cache the position of the element if we can
if (document && document.body) {
this.setInitPosition();
}
// add to an interaction group
this.addToGroup((sGroup) ? sGroup : "default");
},
/**
* Configures the padding for the target zone in px. Effectively expands
* (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.
* @param {int} iTop Top pad
* @param {int} iRight Right pad
* @param {int} iBot Bot pad
* @param {int} iLeft Left pad
*/
setPadding: function(iTop, iRight, iBot, iLeft) {
// this.padding = [iLeft, iRight, iTop, iBot];
if (!iRight && 0 !== iRight) {
this.padding = [iTop, iTop, iTop, iTop];
} else if (!iBot && 0 !== iBot) {
this.padding = [iTop, iRight, iTop, iRight];
} else {
this.padding = [iTop, iRight, iBot, iLeft];
}
},
/**
* Stores the initial placement of the dd element
*/
setInitPosition: function(diffX, diffY) {
var el = this.getEl();
if (!this.DDM.verifyEl(el)) {
this.logger.debug(this.id + " element is broken");
return;
}
var dx = diffX || 0;
var dy = diffY || 0;
var p = YAHOO.util.Dom.getXY( el );
this.initPageX = p[0] - dx;
this.initPageY = p[1] - dy;
this.lastPageX = p[0];
this.lastPageY = p[1];
this.setStartPosition(p);
},
/**
* Sets the start position of the element. This is set when the obj
* is initialized, the reset when a drag is started.
* @param pos current position (from previous lookup)
* @private
*/
setStartPosition: function(pos) {
var p = pos || YAHOO.util.Dom.getXY( this.getEl() );
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
* groups as needed.
*
* @param sGroup {string} the name of the group
*/
addToGroup: function(sGroup) {
this.groups[sGroup] = true;
this.DDM.regDragDrop(this, sGroup);
},
/**
* 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
*/
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
* content area would normally start the drag operation. Use this method
* 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
*/
setHandleElId: function(id) {
this.handleElId = id;
this.DDM.regHandle(this.id, id);
},
/**
* Allows you to set an element outside of the linked element as a drag
* handle
*/
setOuterHandleElId: function(id) {
this.logger.debug("Adding outer handle event: " + id);
YAHOO.util.Event.addListener(id, "mousedown",
this.handleMouseDown, this, true);
this.setHandleElId(id);
},
/**
* Remove all drag and drop hooks for this element
*/
unreg: function() {
this.logger.debug("DragDrop obj cleanup " + this.id);
YAHOO.util.Event.removeListener(this.id, "mousedown",
this.handleMouseDown);
this._domRef = null;
this.DDM._remove(this);
},
/**
* 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
* false
*/
isLocked: function() {
return (this.DDM.isLocked() || this.locked);
},
/**
* Fired when this object is clicked
*
* @param {Event} e
* @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
* @private
*/
handleMouseDown: function(e, oDD) {
this.logger.debug("isLocked: " + this.isLocked());
var EU = YAHOO.util.Event;
var button = e.which || e.button;
this.logger.debug("button: " + button);
if (this.primaryButtonOnly && button > 1) {
this.logger.debug("Mousedown was not produced by the primary button");
return;
}
if (this.isLocked()) {
this.logger.debug("Drag and drop is disabled, aborting");
return;
}
this.logger.debug("mousedown " + this.id);
this.DDM.refreshCache(this.groups);
// 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) ) {
this.logger.debug("click is legit");
// 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();
this.logger.debug("firing onMouseDown events");
this.b4MouseDown(e);
this.onMouseDown(e);
this.DDM.handleMouseDown(e, this);
this.DDM.stopEvent(e);
}
}
},
/**
* 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.
*
* @param {string} tagName the type of element to exclude
*/
addInvalidHandleType: function(tagName) {
var type = tagName.toUpperCase();
this.invalidHandleTypes[type] = type;
},
/**
* Unsets an excluded tag name set by addInvalidHandleType
*
* @param {string} tagName the type of element to unexclude
*/
removeInvalidHandleType: function(tagName) {
var type = tagName.toUpperCase();
this.invalidHandleTypes[type] = null;
},
/**
* Checks the tag exclusion list to see if this click should be ignored
*
* @param {ygNode} node
* @return {boolean} true if this is a valid tag type, false if not
*/
isValidHandleChild: function(node) {
var type = node.nodeName;
if (type == "#text") {
// this.logger.debug("text node, getting parent node type");
type = node.parentNode.nodeName;
}
return (!this.invalidHandleTypes[type]);
},
/**
* Create the array of horizontal tick marks if an interval was specified
* in setXConstraint().
*
* @private
*/
setXTicks: function(iStartX, iTickSize) {
this.xTicks = [];
this.xTickSize = iTickSize;
var tickMap = {};
for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
if (!tickMap[i]) {
this.xTicks[this.xTicks.length] = i;
tickMap[i] = true;
}
}
for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
if (!tickMap[i]) {
this.xTicks[this.xTicks.length] = i;
tickMap[i] = true;
}
}
this.xTicks.sort(this.DDM.numericSort) ;
this.logger.debug("xTicks: " + this.xTicks.join());
},
/**
* Create the array of vertical tick marks if an interval was specified in
* setYConstraint().
*
* @private
*/
setYTicks: function(iStartY, iTickSize) {
this.yTicks = [];
this.yTickSize = iTickSize;
var tickMap = {};
for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
if (!tickMap[i]) {
this.yTicks[this.yTicks.length] = i;
tickMap[i] = true;
}
}
for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
if (!tickMap[i]) {
this.yTicks[this.yTicks.length] = i;
tickMap[i] = true;
}
}
this.yTicks.sort(this.DDM.numericSort) ;
this.logger.debug("yTicks: " + this.yTicks.join());
},
/**
* 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.
*
* @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
* right
* @param {int} iTickSize optional parameter for specifying that the
* element
* should move iTickSize pixels at a time.
*/
setXConstraint: function(iLeft, iRight, iTickSize) {
this.leftConstraint = iLeft;
this.rightConstraint = iRight;
this.minX = this.initPageX - iLeft;
this.maxX = this.initPageX + iRight;
if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
this.constrainX = true;
this.logger.debug("initPageX:" + this.initPageX + " minX:" + this.minX +
" maxX:" + this.maxX);
},
/**
* 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.
*
* @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
* element should move iTickSize pixels at a time.
*/
setYConstraint: function(iUp, iDown, iTickSize) {
this.topConstraint = iUp;
this.bottomConstraint = iDown;
this.minY = this.initPageY - iUp;
this.maxY = this.initPageY + iDown;
if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
this.constrainY = true;
this.logger.debug("initPageY:" + this.initPageY + " minY:" + this.minY +
" maxY:" + this.maxY);
},
/**
* resetConstraints must be called if you manually reposition a dd element.
* @param {boolean} maintainOffset
*/
resetConstraints: function() {
// this.logger.debug("init pagexy: " + this.initPageX + ", " +
// this.initPageY);
// this.logger.debug("last pagexy: " + this.lastPageX + ", " +
// this.lastPageY);
// figure out how much this thing has moved
var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
// this.logger.debug("diff: " + dx + ", " + dy);
// reset the initial location
this.setInitPosition(dx, dy);
if (this.constrainX) {
this.setXConstraint( this.leftConstraint,
this.rightConstraint,
this.xTickSize );
}
if (this.constrainY) {
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
* location when we have it set up like this.
*
* @param {int} val where we want to place the object
* @param {int[]} tickArray sorted array of valid points
* @return {int} the closest tick
* @private
*/
getTick: function(val, tickArray) {
if (!tickArray) {
// If tick interval is not defined, it is effectively 1 pixel,
// so we return the value passed to us.
return val;
} else if (tickArray[0] >= val) {
// The value is lower than the first tick, so we return the first
// tick.
return tickArray[0];
} else {
for (var i = 0; i < tickArray.length; ++i) {
var next = i + 1;
if (tickArray[next] && tickArray[next] >= val) {
var diff1 = val - tickArray[i];
var diff2 = tickArray[next] - val;
return (diff2 > diff1) ? tickArray[i] : tickArray[next];
}
}
// The value is larger than the last tick, so we return the last
// tick.
return tickArray[tickArray.length - 1];
}
},
/**
* toString method
* @return {string} string representation of the dd obj
*/
toString: function(val, tickArray) {
return ("YAHOO.util.DragDrop {" + this.id + "}");
}
};
/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
// Only load the library once. Rewriting the manager class would orphan
// existing drag and drop instances.
if (!YAHOO.util.DragDropMgr) {
/**
* @class 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() {
/**
* utility package shorthand
* @private
*/
var UTIL = YAHOO.util;
/**
* Two dimensional Array of registered DragDrop objects. The first
* dimension is the DragDrop item group, the second the DragDrop
* object.
*
* @private
*/
this.ids = {};
/**
* 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.
*
* @private
*/
this.handleIds = {};
/**
* the DragDrop object that is currently being dragged
*
* @type DragDrop
* @private
**/
this.dragCurrent = null;
/**
* the DragDrop object(s) that are being hovered over
*
* @type Array
* @private
*/
this.dragOvers = {};
/**
* @private
*/
this.logger = null;
/**
* the X distance between the cursor and the object being dragged
*
* @type int
* @private
*/
this.deltaX = 0;
/**
* the Y distance between the cursor and the object being dragged
*
* @type int
* @private
*/
this.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
* false if you need the default behavior (not recommended)
*
* @type boolean
*/
this.preventDefault = true;
/**
* 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.
*
* @type boolean
*/
this.stopPropagation = true;
/**
* @private
*/
this.initalized = false;
/**
* All drag and drop can be disabled.
*
* @private
*/
this.locked = false;
/**
* Called the first time an element is registered.
*
* @private
*/
this.init = function() {
this.logger = new ygLogger("DragDropMgr");
};
/**
* In point mode, drag and drop interaction is defined by the
* location of the cursor during the drag/drop
* @type int
*/
this.POINT = 0;
/**
* In intersect mode, drag and drop interactio nis defined by the
* overlap of two or more drag and drop objects.
* @type int
*/
this.INTERSECT = 1;
/**
* The current drag and drop mode. Default it point mode
* @type int
*/
this.mode = this.POINT;
/**
* Runs method on all drag and drop objects
* @private
*/
this._execOnAll = function(sMethod, args) {
for (var i in this.ids) {
for (var j in this.ids[i]) {
var oDD = this.ids[i][j];
if (! this.isTypeOfDD(oDD)) {
continue;
}
oDD[sMethod].apply(oDD, args);
}
}
};
/**
* Drag and drop initialization. Sets up the global event handlers
* @private
*/
this._onLoad = function() {
this._execOnAll("setInitPosition", []);
this.logger = new ygLogger("DragDropMgr");
this.logger.debug("DDM onload");
var EU = UTIL.Event;
EU.addListener(document, "mouseup", this.handleMouseUp, this, true);
EU.addListener(document, "mousemove", this.handleMouseMove, this, true);
EU.addListener(window, "unload", this._onUnload, this, true);
EU.addListener(window, "resize", this._onResize, this, true);
// EU.addListener(window, "mouseout", this._test);
this.initalized = true;
};
/**
* Reset constraints on all drag and drop objs
* @private
*/
this._onResize = function(e) {
this.logger.debug("window resize");
this._execOnAll("resetConstraints", []);
};
/**
* Lock all drag and drop functionality
*/
this.lock = function() { this.locked = true; };
/**
* Unlock all drag and drop functionality
*/
this.unlock = function() { this.locked = false; };
/**
* Is drag and drop locked?
*
* @return {boolean} True if drag and drop is locked, false otherwise.
*/
this.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.
*
* @private
*/
this.locationCache = {};
/**
* Set useCache to false if you want to force object the lookup of each
* drag and drop linked element constantly during a drag.
* @type boolean
*/
this.useCache = true;
/**
* The number of pixels that the mouse needs to move after the
* mousedown before the drag is initiated. Default=3;
* @type int
*/
this.clickPixelThresh = 3;
/**
* The number of milliseconds after the mousedown event to initiate the
* drag if we don't get a mouseup event. Default=1000
* @type int
*/
this.clickTimeThresh = 1000;
/**
* Flag that indicates that either the drag pixel threshold or the
* mousdown time threshold has been met
* @type boolean
* @private
*/
this.dragThreshMet = false;
/**
* Timeout used for the click time threshold
* @type Object
* @private
*/
this.clickTimeout = null;
/**
* The X position of the mousedown event stored for later use when a
* drag threshold is met.
* @type int
* @private
*/
this.startX = 0;
/**
* The Y position of the mousedown event stored for later use when a
* drag threshold is met.
* @type int
* @private
*/
this.startY = 0;
/**
* Each DragDrop instance must be registered with the DragDropMgr.
* This is executed in ygDragDrop.init()
*
* @param {DragDrop} oDD the DragDrop object to register
* @param {String} sGroup the name of the group this element belongs to
*/
this.regDragDrop = function(oDD, sGroup) {
if (!this.initialized) { this.init(); }
if (!this.ids[sGroup]) {
this.ids[sGroup] = {};
}
this.ids[sGroup][oDD.id] = oDD;
};
/**
* Unregisters a drag and drop item. This is executed in
* ygDragDrop.unreg, use that method instead of calling this directly.
* @private
*/
this._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 ygDragDrop.setHandleElId()
*
* @param {String} sDDId the DragDrop id this element is a handle for
* @param {String} sHandleId the id of the element that is the drag
* handle
*/
this.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
* registered as a drag drop item.
*
* @param {String} id the element id to check
* @return {boolean} true if this element is a DragDrop item,
* false otherwise
*/
this.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.
*
* @param {ygDragDrop} p_oDD the obj to get related data for
* @param {boolean} bTargetsOnly if true, only return targetable objs
* @return {ygDragDrop[]} the related instances
*/
this.getRelated = function(p_oDD, bTargetsOnly) {
var oDDs = [];
for (var i in p_oDD.groups) {
for (j in this.ids[i]) {
var dd = this.ids[i][j];
if (! this.isTypeOfDD(dd)) {
continue;
}
if (!bTargetsOnly || dd.isTarget) {
oDDs[oDDs.length] = dd;
}
}
}
return oDDs;
};
/**
* Returns true if the specified dd target is a legal target for
* the specifice drag obj
*
* @param {ygDragDrop} the drag obj
* @param {ygDragDrop) the target
* @return {boolean} true if the target is a legal target for the
* dd obj
*/
this.isLegalTarget = function (oDD, oTargetDD) {
var targets = this.getRelated(oDD);
for (var i =0;i