AutorÃa | Ultima modificación | Ver Log |
YUI.add('yui2-dragdrop', function(Y) {var YAHOO = Y.YUI2;/*Copyright (c) 2011, Yahoo! Inc. All rights reserved.Code licensed under the BSD License:http://developer.yahoo.com/yui/license.htmlversion: 2.9.0*//*** 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) {/*** 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,Dom = YAHOO.util.Dom;return {/*** This property is used to turn on global use of the shim element on all DragDrop instances, defaults to false for backcompat. (Use: YAHOO.util.DDM.useShim = true)* @property useShim* @type Boolean* @static*/useShim: false,/*** This property is used to determine if the shim is active over the screen, default false.* @private* @property _shimActive* @type Boolean* @static*/_shimActive: false,/*** This property is used when useShim is set on a DragDrop object to store the current state of DDM.useShim so it can be reset when a drag operation is done.* @private* @property _shimState* @type Boolean* @static*/_shimState: false,/*** This property is used when useShim is set to true, it will set the opacity on the shim to .5 for debugging. Use: (YAHOO.util.DDM._debugShim = true;)* @private* @property _debugShim* @type Boolean* @static*/_debugShim: false,/*** This method will create a shim element (giving it the id of yui-ddm-shim), it also attaches the mousemove and mouseup listeners to it and attaches a scroll listener on the window* @private* @method _sizeShim* @static*/_createShim: function() {var s = document.createElement('div');s.id = 'yui-ddm-shim';if (document.body.firstChild) {document.body.insertBefore(s, document.body.firstChild);} else {document.body.appendChild(s);}s.style.display = 'none';s.style.backgroundColor = 'red';s.style.position = 'absolute';s.style.zIndex = '99999';Dom.setStyle(s, 'opacity', '0');this._shim = s;Event.on(s, "mouseup", this.handleMouseUp, this, true);Event.on(s, "mousemove", this.handleMouseMove, this, true);Event.on(window, 'scroll', this._sizeShim, this, true);},/*** This method will size the shim, called from activate and on window scroll event* @private* @method _sizeShim* @static*/_sizeShim: function() {if (this._shimActive) {var s = this._shim;s.style.height = Dom.getDocumentHeight() + 'px';s.style.width = Dom.getDocumentWidth() + 'px';s.style.top = '0';s.style.left = '0';}},/*** This method will create the shim element if needed, then show the shim element, size the element and set the _shimActive property to true* @private* @method _activateShim* @static*/_activateShim: function() {if (this.useShim) {if (!this._shim) {this._createShim();}this._shimActive = true;var s = this._shim,o = '0';if (this._debugShim) {o = '.5';}Dom.setStyle(s, 'opacity', o);this._sizeShim();s.style.display = 'block';}},/*** This method will hide the shim element and set the _shimActive property to false* @private* @method _deactivateShim* @static*/_deactivateShim: function() {this._shim.style.display = 'none';this._shimActive = false;},/*** The HTML element created to use as a shim over the document to track mouse movements* @private* @property _shim* @type HTMLElement* @static*/_shim: null,/*** 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*/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.* @property handleIds* @type {string: string}* @private* @static*/handleIds: {},/*** the DragDrop object that is currently being dragged* @property dragCurrent* @type DragDrop* @private* @static**/dragCurrent: null,/*** the DragDrop object(s) that are being hovered over* @property dragOvers* @type Array* @private* @static*/dragOvers: {},/*** the X distance between the cursor and the object being dragged* @property deltaX* @type int* @private* @static*/deltaX: 0,/*** the Y distance between the cursor and the object being dragged* @property deltaY* @type int* @private* @static*/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)* @property preventDefault* @type boolean* @static*/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.* @property stopPropagation* @type boolean* @static*/stopPropagation: true,/*** Internal flag that is set to true when drag and drop has been* initialized* @property initialized* @private* @static*/initialized: false,/*** All drag and drop can be disabled.* @property locked* @private* @static*/locked: false,/*** Provides additional information about the the current set of* interactions. Can be accessed from the event handlers. It* contains the following properties:** out: onDragOut interactions* enter: onDragEnter interactions* over: onDragOver interactions* drop: onDragDrop interactions* point: The location of the cursor* draggedRegion: The location of dragged element at the time* of the interaction* sourceRegion: The location of the source elemtn at the time* of the interaction* validDrop: boolean* @property interactionInfo* @type object* @static*/interactionInfo: null,/*** Called the first time an element is registered.* @method init* @private* @static*/init: function() {this.initialized = true;},/*** 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*/POINT: 0,/*** 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*/STRICT_INTERSECT: 2,/*** The current drag and drop mode. Default: POINT* @property mode* @type int* @static*/mode: 0,/*** Runs method on all drag and drop objects* @method _execOnAll* @private* @static*/_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* @method _onLoad* @private* @static*/_onLoad: function() {this.init();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);},/*** Reset constraints on all drag and drop objs* @method _onResize* @private* @static*/_onResize: function(e) {this._execOnAll("resetConstraints", []);},/*** Lock all drag and drop functionality* @method lock* @static*/lock: function() { this.locked = true; },/*** Unlock all drag and drop functionality* @method unlock* @static*/unlock: function() { this.locked = false; },/*** Is drag and drop locked?* @method isLocked* @return {boolean} True if drag and drop is locked, false otherwise.* @static*/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*/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*/useCache: true,/*** 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*/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*/clickTimeThresh: 1000,/*** Flag that indicates that either the drag pixel threshold or the* mousdown time threshold has been met* @property dragThreshMet* @type boolean* @private* @static*/dragThreshMet: false,/*** Timeout used for the click time threshold* @property clickTimeout* @type Object* @private* @static*/clickTimeout: null,/*** The X position of the mousedown event stored for later use when a* drag threshold is met.* @property startX* @type int* @private* @static*/startX: 0,/*** The Y position of the mousedown event stored for later use when a* drag threshold is met.* @property startY* @type int* @private* @static*/startY: 0,/*** Flag to determine if the drag event was fired from the click timeout and* not the mouse move threshold.* @property fromTimeout* @type boolean* @private* @static*/fromTimeout: false,/*** 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*/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, so don't call this function directly.* @method removeDDFromGroup* @private* @static*/removeDDFromGroup: function(oDD, sGroup) {if (!this.ids[sGroup]) {this.ids[sGroup] = {};}var obj = this.ids[sGroup];if (obj && obj[oDD.id]) {delete obj[oDD.id];}},/*** Unregisters a drag and drop item. This is executed in* DragDrop.unreg, use that method instead of calling this directly.* @method _remove* @private* @static*/_remove: function(oDD) {for (var g in oDD.groups) {if (g) {var item = this.ids[g];if (item && item[oDD.id]) {delete item[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* handle* @static*/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.* @method isDragDrop* @param {String} id the element id to check* @return {boolean} true if this element is a DragDrop item,* false otherwise* @static*/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*/getRelated: function(p_oDD, bTargetsOnly) {var oDDs = [];for (var i in p_oDD.groups) {for (var 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* @method isLegalTarget* @param {DragDrop} the drag obj* @param {DragDrop} the target* @return {boolean} true if the target is a legal target for the* dd obj* @static*/isLegalTarget: function (oDD, oTargetDD) {var targets = this.getRelated(oDD, true);for (var i=0, len=targets.length;i<len;++i) {if (targets[i].id == oTargetDD.id) {return true;}}return false;},/*** My goal is to be able to transparently determine if an object is* typeof DragDrop, and the exact subclass of DragDrop. typeof* returns "object", oDD.constructor.toString() always returns* "DragDrop" and not the name of the subclass. So for now it just* evaluates a well-known variable in DragDrop.* @method isTypeOfDD* @param {Object} the object to evaluate* @return {boolean} true if typeof oDD = DragDrop* @static*/isTypeOfDD: function (oDD) {return (oDD && oDD.__ygDragDrop);},/*** Utility function to determine if a given element has been* registered as a drag drop handle for the given Drag Drop object.* @method isHandle* @param {String} id the element id to check* @return {boolean} true if this element is a DragDrop handle, false* otherwise* @static*/isHandle: function(sDDId, sHandleId) {return ( this.handleIds[sDDId] &&this.handleIds[sDDId][sHandleId] );},/*** Returns the DragDrop instance for a given id* @method getDDById* @param {String} id the id of the DragDrop object* @return {DragDrop} the drag drop object, null if it is not found* @static*/getDDById: function(id) {for (var i in this.ids) {if (this.ids[i][id]) {return this.ids[i][id];}}return null;},/*** Fired after a registered DragDrop object gets the mousedown event.* Sets up the events required to track the object being dragged* @method handleMouseDown* @param {Event} e the event* @param oDD the DragDrop object being dragged* @private* @static*/handleMouseDown: function(e, oDD) {//this._activateShim();this.currentTarget = YAHOO.util.Event.getTarget(e);this.dragCurrent = oDD;var el = oDD.getEl();// track start positionthis.startX = YAHOO.util.Event.getPageX(e);this.startY = YAHOO.util.Event.getPageY(e);this.deltaX = this.startX - el.offsetLeft;this.deltaY = this.startY - el.offsetTop;this.dragThreshMet = false;this.clickTimeout = setTimeout(function() {var DDM = YAHOO.util.DDM;DDM.startDrag(DDM.startX, DDM.startY);DDM.fromTimeout = true;},this.clickTimeThresh );},/*** Fired when either the drag pixel threshold or the mousedown hold* time threshold has been met.* @method startDrag* @param x {int} the X position of the original mousedown* @param y {int} the Y position of the original mousedown* @static*/startDrag: function(x, y) {if (this.dragCurrent && this.dragCurrent.useShim) {this._shimState = this.useShim;this.useShim = true;}this._activateShim();clearTimeout(this.clickTimeout);var dc = this.dragCurrent;if (dc && dc.events.b4StartDrag) {dc.b4StartDrag(x, y);dc.fireEvent('b4StartDragEvent', { x: x, y: y });}if (dc && dc.events.startDrag) {dc.startDrag(x, y);dc.fireEvent('startDragEvent', { x: x, y: y });}this.dragThreshMet = true;},/*** Internal function to handle the mouseup event. Will be invoked* from the context of the document.* @method handleMouseUp* @param {Event} e the event* @private* @static*/handleMouseUp: function(e) {if (this.dragCurrent) {clearTimeout(this.clickTimeout);if (this.dragThreshMet) {if (this.fromTimeout) {this.fromTimeout = false;this.handleMouseMove(e);}this.fromTimeout = false;this.fireEvents(e, true);} else {}this.stopDrag(e);this.stopEvent(e);}},/*** Utility to stop event propagation and event default, if these* features are turned on.* @method stopEvent* @param {Event} e the event as returned by this.getEvent()* @static*/stopEvent: function(e) {if (this.stopPropagation) {YAHOO.util.Event.stopPropagation(e);}if (this.preventDefault) {YAHOO.util.Event.preventDefault(e);}},/*** Ends the current drag, cleans up the state, and fires the endDrag* and mouseUp events. Called internally when a mouseup is detected* during the drag. Can be fired manually during the drag by passing* either another event (such as the mousemove event received in onDrag)* or a fake event with pageX and pageY defined (so that endDrag and* onMouseUp have usable position data.). Alternatively, pass true* for the silent parameter so that the endDrag and onMouseUp events* are skipped (so no event data is needed.)** @method stopDrag* @param {Event} e the mouseup event, another event (or a fake event)* with pageX and pageY defined, or nothing if the* silent parameter is true* @param {boolean} silent skips the enddrag and mouseup events if true* @static*/stopDrag: function(e, silent) {var dc = this.dragCurrent;// Fire the drag end event for the item that was draggedif (dc && !silent) {if (this.dragThreshMet) {if (dc.events.b4EndDrag) {dc.b4EndDrag(e);dc.fireEvent('b4EndDragEvent', { e: e });}if (dc.events.endDrag) {dc.endDrag(e);dc.fireEvent('endDragEvent', { e: e });}}if (dc.events.mouseUp) {dc.onMouseUp(e);dc.fireEvent('mouseUpEvent', { e: e });}}if (this._shimActive) {this._deactivateShim();if (this.dragCurrent && this.dragCurrent.useShim) {this.useShim = this._shimState;this._shimState = false;}}this.dragCurrent = null;this.dragOvers = {};},/*** Internal function to handle the mousemove event. Will be invoked* from the context of the html element.** @TODO figure out what we can do about mouse events lost when the* user drags objects beyond the window boundary. Currently we can* detect this in internet explorer by verifying that the mouse is* down during the mousemove event. Firefox doesn't give us the* button state on the mousemove event.* @method handleMouseMove* @param {Event} e the event* @private* @static*/handleMouseMove: function(e) {var dc = this.dragCurrent;if (dc) {// var button = e.which || e.button;// check for IE < 9 mouseup outside of page boundaryif (YAHOO.env.ua.ie && (YAHOO.env.ua.ie < 9) && !e.button) {this.stopEvent(e);return this.handleMouseUp(e);} else {if (e.clientX < 0 || e.clientY < 0) {//This will stop the element from leaving the viewport in FF, Opera & Safari//Not turned on yet//this.stopEvent(e);//return false;}}if (!this.dragThreshMet) {var diffX = Math.abs(this.startX - YAHOO.util.Event.getPageX(e));var diffY = Math.abs(this.startY - YAHOO.util.Event.getPageY(e));if (diffX > this.clickPixelThresh ||diffY > this.clickPixelThresh) {this.startDrag(this.startX, this.startY);}}if (this.dragThreshMet) {if (dc && dc.events.b4Drag) {dc.b4Drag(e);dc.fireEvent('b4DragEvent', { e: e});}if (dc && dc.events.drag) {dc.onDrag(e);dc.fireEvent('dragEvent', { e: e});}if (dc) {this.fireEvents(e, false);}}this.stopEvent(e);}},/*** 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*/fireEvents: function(e, isDrop) {var dc = this.dragCurrent;// If the user did the mouse up outside of the window, we could// get here even though we have ended the drag.// If the config option dragOnly is true, bail out and don't fire the eventsif (!dc || dc.isLocked() || dc.dragOnly) {return;}var x = YAHOO.util.Event.getPageX(e),y = YAHOO.util.Event.getPageY(e),pt = new YAHOO.util.Point(x,y),pos = dc.getTargetCoord(pt.x, pt.y),el = dc.getDragEl(),events = ['out', 'over', 'drop', 'enter'],curRegion = new YAHOO.util.Region( pos.y,pos.x + el.offsetWidth,pos.y + el.offsetHeight,pos.x ),oldOvers = [], // cache the previous dragOver arrayinGroupsObj = {},b4Results = {},inGroups = [],data = {outEvts: [],overEvts: [],dropEvts: [],enterEvts: []};// Check to see if the object(s) we were hovering over is no longer// being hovered over so we can fire the onDragOut eventfor (var i in this.dragOvers) {var ddo = this.dragOvers[i];if (! this.isTypeOfDD(ddo)) {continue;}if (! this.isOverTarget(pt, ddo, this.mode, curRegion)) {data.outEvts.push( ddo );}oldOvers[i] = true;delete this.dragOvers[i];}for (var sGroup in dc.groups) {if ("string" != typeof sGroup) {continue;}for (i in this.ids[sGroup]) {var oDD = this.ids[sGroup][i];if (! this.isTypeOfDD(oDD)) {continue;}if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {if (this.isOverTarget(pt, oDD, this.mode, curRegion)) {inGroupsObj[sGroup] = true;// look for drop interactionsif (isDrop) {data.dropEvts.push( oDD );// look for drag enter and drag over interactions} else {// initial drag over: dragEnter firesif (!oldOvers[oDD.id]) {data.enterEvts.push( oDD );// subsequent drag overs: dragOver fires} else {data.overEvts.push( oDD );}this.dragOvers[oDD.id] = oDD;}}}}}this.interactionInfo = {out: data.outEvts,enter: data.enterEvts,over: data.overEvts,drop: data.dropEvts,point: pt,draggedRegion: curRegion,sourceRegion: this.locationCache[dc.id],validDrop: isDrop};for (var inG in inGroupsObj) {inGroups.push(inG);}// notify about a drop that did not find a targetif (isDrop && !data.dropEvts.length) {this.interactionInfo.validDrop = false;if (dc.events.invalidDrop) {dc.onInvalidDrop(e);dc.fireEvent('invalidDropEvent', { e: e });}}for (i = 0; i < events.length; i++) {var tmp = null;if (data[events[i] + 'Evts']) {tmp = data[events[i] + 'Evts'];}if (tmp && tmp.length) {var type = events[i].charAt(0).toUpperCase() + events[i].substr(1),ev = 'onDrag' + type,b4 = 'b4Drag' + type,cev = 'drag' + type + 'Event',check = 'drag' + type;if (this.mode) {if (dc.events[b4]) {dc[b4](e, tmp, inGroups);b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp, group: inGroups });}if (dc.events[check] && (b4Results[ev] !== false)) {dc[ev](e, tmp, inGroups);dc.fireEvent(cev, { event: e, info: tmp, group: inGroups });}} else {for (var b = 0, len = tmp.length; b < len; ++b) {if (dc.events[b4]) {dc[b4](e, tmp[b].id, inGroups[0]);b4Results[ev] = dc.fireEvent(b4 + 'Event', { event: e, info: tmp[b].id, group: inGroups[0] });}if (dc.events[check] && (b4Results[ev] !== false)) {dc[ev](e, tmp[b].id, inGroups[0]);dc.fireEvent(cev, { event: e, info: tmp[b].id, group: inGroups[0] });}}}}}},/*** Helper function for getting the best match from the list of drag* and drop objects returned by the drag and drop events when we are* in INTERSECT mode. It returns either the first object that the* cursor is over, or the object that has the greatest overlap with* the dragged element.* @method getBestMatch* @param {DragDrop[]} dds The array of drag and drop objects* targeted* @return {DragDrop} The best single match* @static*/getBestMatch: function(dds) {var winner = null;var len = dds.length;if (len == 1) {winner = dds[0];} else {// Loop through the targeted itemsfor (var i=0; i<len; ++i) {var dd = dds[i];// If the cursor is over the object, it wins. If the// cursor is over multiple matches, the first one we come// to wins.if (this.mode == this.INTERSECT && dd.cursorIsOver) {winner = dd;break;// Otherwise the object with the most overlap wins} else {if (!winner || !winner.overlap || (dd.overlap &&winner.overlap.getArea() < dd.overlap.getArea())) {winner = dd;}}}}return winner;},/*** Refreshes the cache of the top-left and bottom-right points of the* drag and drop objects in the specified group(s). This is in the* format that is stored in the drag and drop instance, so typical* usage is:* <code>* YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups);* </code>* Alternatively:* <code>* YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true});* </code>* @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*/refreshCache: function(groups) {// refresh everything if group array is not providedvar g = groups || this.ids;for (var sGroup in g) {if ("string" != typeof sGroup) {continue;}for (var i in this.ids[sGroup]) {var oDD = this.ids[sGroup][i];if (this.isTypeOfDD(oDD)) {var loc = this.getLocation(oDD);if (loc) {this.locationCache[oDD.id] = loc;} else {delete this.locationCache[oDD.id];}}}}},/*** 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*/verifyEl: function(el) {try {if (el) {var parent = el.offsetParent;if (parent) {return true;}}} catch(e) {}return false;},/*** 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*/getLocation: function(oDD) {if (! this.isTypeOfDD(oDD)) {return null;}var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;try {pos= YAHOO.util.Dom.getXY(el);} catch (e) { }if (!pos) {return null;}x1 = pos[0];x2 = x1 + el.offsetWidth;y1 = pos[1];y2 = y1 + el.offsetHeight;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* @param {boolean} intersect true if we are in intersect mode* @param {YAHOO.util.Region} pre-cached location of the dragged element* @return {boolean} true if the mouse is over the target* @private* @static*/isOverTarget: function(pt, oTarget, intersect, curRegion) {// use cache if availablevar loc = this.locationCache[oTarget.id];if (!loc || !this.useCache) {loc = this.getLocation(oTarget);this.locationCache[oTarget.id] = loc;}if (!loc) {return false;}oTarget.cursorIsOver = loc.contains( pt );// 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 done. Otherwise we need to evaluate the// region the target as occupies to determine if the dragged element// overlaps with it.var dc = this.dragCurrent;if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {//if (oTarget.cursorIsOver) {//}return oTarget.cursorIsOver;}oTarget.overlap = null;// Get the current location of the drag element, this is the// location of the mouse event less the delta that represents// where the original mousedown happened on the element. We// need to consider constraints and ticks as well.if (!curRegion) {var pos = dc.getTargetCoord(pt.x, pt.y);var el = dc.getDragEl();curRegion = new YAHOO.util.Region( pos.y,pos.x + el.offsetWidth,pos.y + el.offsetHeight,pos.x );}var overlap = curRegion.intersect(loc);if (overlap) {oTarget.overlap = overlap;return (intersect) ? true : oTarget.cursorIsOver;} else {return false;}},/*** unload event handler* @method _onUnload* @private* @static*/_onUnload: function(e, me) {this.unregAll();},/*** Cleans up the drag and drop events and objects.* @method unregAll* @private* @static*/unregAll: function() {if (this.dragCurrent) {this.stopDrag();this.dragCurrent = null;}this._execOnAll("unreg", []);//for (var i in this.elementCache) {//delete this.elementCache[i];//}//this.elementCache = {};this.ids = {};},/*** A cache of DOM elements* @property elementCache* @private* @static* @deprecated elements are not cached now*/elementCache: {},/*** Get the wrapper for the DOM element specified* @method getElWrapper* @param {String} id the id of the element to get* @return {YAHOO.util.DDM.ElementWrapper} the wrapped element* @private* @deprecated This wrapper isn't that useful* @static*/getElWrapper: function(id) {var oWrapper = this.elementCache[id];if (!oWrapper || !oWrapper.el) {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 use YAHOO.util.Dom.get instead* @static*/getElement: function(id) {return YAHOO.util.Dom.get(id);},/*** 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 use YAHOO.util.Dom instead* @static*/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*/ElementWrapper: function(el) {/*** The element* @property el*/this.el = el || null;/*** The element id* @property id*/this.id = this.el && el.id;/*** 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* @for DragDropMgr* @deprecated use YAHOO.util.Dom.getX instead* @static*/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 use YAHOO.util.Dom.getY instead* @static*/getPosY: function(el) {return YAHOO.util.Dom.getY(el);},/*** 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*/swapNode: function(n1, n2) {if (n1.swapNode) {n1.swapNode(n2);} else {var p = n2.parentNode;var s = n2.nextSibling;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*/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 {}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* @static*/getStyle: function(el, styleProp) {return YAHOO.util.Dom.getStyle(el, styleProp);},/*** Gets the scrollTop* @method getScrollTop* @return {int} the document's scrollTop* @static*/getScrollTop: function () { return this.getScroll().top; },/*** Gets the scrollLeft* @method getScrollLeft* @return {int} the document's scrollTop* @static*/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*/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 use YAHOO.util.Dom.getViewportHeight instead* @static*/getClientHeight: function() {return YAHOO.util.Dom.getViewportHeight();},/*** Gets the client width* @method getClientWidth* @return {int} client width in px* @deprecated use YAHOO.util.Dom.getViewportWidth instead* @static*/getClientWidth: function() {return YAHOO.util.Dom.getViewportWidth();},/*** Numeric array sort function* @method numericSort* @static*/numericSort: function(a, b) { return (a - b); },/*** Internal counter* @property _timeoutCount* @private* @static*/_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*/_addListeners: function() {var DDM = YAHOO.util.DDM;if ( YAHOO.util.Event && document ) {DDM._onLoad();} else {if (DDM._timeoutCount > 2000) {} else {setTimeout(DDM._addListeners, 10);if (document && document.body) {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* clicked.* @method handleWasClicked* @param node the html element to inspect* @static*/handleWasClicked: function(node, id) {if (this.isHandle(id, node.id)) {return true;} else {// check to see if this is a text node child of the one we wantvar p = node.parentNode;while (p) {if (this.isHandle(id, p.id)) {return true;} else {p = p.parentNode;}}}return false;}};}();// shorter alias, save a few bytesYAHOO.util.DDM = YAHOO.util.DragDropMgr;YAHOO.util.DDM._addListeners();}(function() {var Event=YAHOO.util.Event;var Dom=YAHOO.util.Dom;/*** 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:* <ul>* <li>linked element: the element that is passed into the constructor.* This is the element which defines the boundaries for interaction with* other DragDrop objects.</li>* <li>handle element(s): The drag operation only occurs if the element that* was clicked matches a handle element. By default this is the linked* element, but there are times that you will want only a portion of the* linked element to initiate the drag operation, and the setHandleElId()* method provides a way to define this.</li>* <li>drag element: this represents an the element that would be moved along* with the cursor during a drag operation. By default, this is the linked* element itself as in {@link YAHOO.util.DD}. setDragElId() lets you define* a separate element that would be moved, as in {@link YAHOO.util.DDProxy}* </li>* </ul>* 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:* <pre>* dd = new YAHOO.util.DragDrop("div1", "group1");* </pre>* 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...* <pre>* dd.onDragDrop = function(e, id) {* alert("dd was dropped on " + id);* }* </pre>* @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,*/YAHOO.util.DragDrop = function(id, sGroup, config) {if (id) {this.init(id, sGroup, config);}};YAHOO.util.DragDrop.prototype = {/*** An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop* By setting any of these to false, then event will not be fired.* @property events* @type object*/events: null,/*** @method on* @description Shortcut for EventProvider.subscribe, see <a href="YAHOO.util.EventProvider.html#subscribe">YAHOO.util.EventProvider.subscribe</a>*/on: function() {this.subscribe.apply(this, arguments);},/*** 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:* YAHOO.util.DDProxy* @property dragElId* @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.* @property handleElId* @type String* @private*/handleElId: null,/*** An associative array of HTML tags that will be ignored if clicked.* @property invalidHandleTypes* @type {string: string}*/invalidHandleTypes: null,/*** An associative array of ids for elements that will be ignored if clicked* @property invalidHandleIds* @type {string: string}*/invalidHandleIds: null,/*** An indexted array of css class names for elements that will be ignored* if clicked.* @property invalidHandleClasses* @type string[]*/invalidHandleClasses: null,/*** 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* 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* 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* 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 instances can be a drop target. This can be disabled by* setting isTarget to false.* @property isTarget* @type boolean*/isTarget: true,/*** The padding configured for this drag and drop object for calculating* the drop zone intersection with this object.* @property padding* @type int[]*/padding: null,/*** If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)* @property dragOnly* @type Boolean*/dragOnly: false,/*** If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls.* @property useShim* @type Boolean*/useShim: false,/*** 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* @property minY* @type int* @type int* @private*/minY: 0,/*** The down constraint* @property maxY* @type int* @private*/maxY: 0,/*** The difference between the click position and the source element's location* @property deltaX* @type int* @private*/deltaX: 0,/*** The difference between the click position and the source element's location* @property deltaY* @type int* @private*/deltaY: 0,/*** 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* 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* when you define a tick interval.* @property yTicks* @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* @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,/*** Property that is assigned to a drag and drop object when testing to* see if it is being targeted by another dd object. This property* can be used in intersect mode to help determine the focus of* the mouse interaction. DDM.getBestMatch uses this property first to* determine the closest match in INTERSECT mode when multiple targets* are part of the same interaction.* @property cursorIsOver* @type boolean*/cursorIsOver: false,/*** Property that is assigned to a drag and drop object when testing to* see if it is being targeted by another dd object. This is a region* that represents the area the draggable element overlaps this target.* DDM.getBestMatch uses this property to compare the size of the overlap* to that of other targets in order to determine the closest match in* INTERSECT mode when multiple targets are part of the same interaction.* @property overlap* @type YAHOO.util.Region*/overlap: null,/*** 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* object.* @method onDrag* @param {Event} e the mousemove event*/onDrag: function(e) { /* override this */ },/*** Abstract method called when this element fist begins hovering over* another DragDrop obj* @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* DragDrop obj* @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* @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* obj* @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* @method endDrag* @param {Event} e the mouseup event*/endDrag: function(e) { /* override this */ },/*** Code executed immediately before the onMouseDown event* @method b4MouseDown* @param {Event} e the mousedown event* @private*/b4MouseDown: function(e) { },/*** Event handler that fires when a drag/drop obj gets a mousedown* @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* @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 () {},/*** Returns a reference to the linked element* @method getEl* @return {HTMLElement} the html element*/getEl: function() {if (!this._domRef) {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* element. An example of this can be found in YAHOO.util.DDProxy* @method getDragEl* @return {HTMLElement} the html element*/getDragEl: function() {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);Event.on(this._domRef || this.id, "mousedown",this.handleMouseDown, this, true);// Event.on(this.id, "selectstart", Event.preventDefault);for (var i in this.events) {this.createEvent(i + 'Event');}},/*** 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 attributesthis.config = config || {};this.events = {};// create a local reference to the drag and drop managerthis.DDM = YAHOO.util.DDM;// initialize the groups objectthis.groups = {};// assume that we have an element reference instead of an id if the// parameter is not a stringif (typeof id !== "string") {this._domRef = id;id = Dom.generateId(id);}// set the idthis.id = id;// add to an interaction groupthis.addToGroup((sGroup) ? sGroup : "default");// 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;Event.onAvailable(id, this.handleOnAvailable, this, true);// the linked element is the element that gets dragged by defaultthis.setDragElId(id);// by default, clicked anchors will not start drag operations.// @TODO what else should be here? Probably form fields.this.invalidHandleTypes = { A: "A" };this.invalidHandleIds = {};this.invalidHandleClasses = [];this.applyConfig();},/*** 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* DragDrop in order to get all of the parameters that are available in* each object.* @method applyConfig*/applyConfig: function() {this.events = {mouseDown: true,b4MouseDown: true,mouseUp: true,b4StartDrag: true,startDrag: true,b4EndDrag: true,endDrag: true,drag: true,b4Drag: true,invalidDrop: true,b4DragOut: true,dragOut: true,dragEnter: true,b4DragOver: true,dragOver: true,b4DragDrop: true,dragDrop: true};if (this.config.events) {for (var i in this.config.events) {if (this.config.events[i] === false) {this.events[i] = false;}}}// configurable properties:// padding, isTarget, maintainOffset, primaryButtonOnlythis.padding = this.config.padding || [0, 0, 0, 0];this.isTarget = (this.config.isTarget !== false);this.maintainOffset = (this.config.maintainOffset);this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);this.dragOnly = ((this.config.dragOnly === true) ? true : false);this.useShim = ((this.config.useShim === true) ? true : false);},/*** Executed when the linked element is available* @method handleOnAvailable* @private*/handleOnAvailable: function() {this.available = true;this.resetConstraints();this.onAvailable();},/*** 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.* @method setPadding* @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 linked element.* @method setInitialPosition* @param {int} diffX the X offset, default 0* @param {int} diffY the Y offset, default 0* @private*/setInitPosition: function(diffX, diffY) {var el = this.getEl();if (!this.DDM.verifyEl(el)) {if (el && el.style && (el.style.display == 'none')) {} else {}return;}var dx = diffX || 0;var dy = diffY || 0;var p = 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.* @method setStartPosition* @param pos current position (from previous lookup)* @private*/setStartPosition: function(pos) {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* groups as needed.* @method addToGroup* @param sGroup {string} the name of the group*/addToGroup: function(sGroup) {this.groups[sGroup] = true;this.DDM.regDragDrop(this, sGroup);},/*** Remove's this instance from the supplied interaction group* @method removeFromGroup* @param {string} sGroup The group to drop*/removeFromGroup: function(sGroup) {if (this.groups[sGroup]) {delete this.groups[sGroup];}this.DDM.removeDDFromGroup(this, sGroup);},/*** Allows you to specify that an element other than the linked element* will be moved with the cursor during a 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* 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.* @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") {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* handle* @method setOuterHandleElId* @param id the id of the element that will be used to initiate the drag*/setOuterHandleElId: function(id) {if (typeof id !== "string") {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() {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.)* @method isLocked* @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* @method handleMouseDown* @param {Event} e* @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)* @private*/handleMouseDown: function(e, oDD) {var button = e.which || e.button;if (this.primaryButtonOnly && button > 1) {return;}if (this.isLocked()) {return;}// firing the mousedown events prior to calculating positionsvar b4Return = this.b4MouseDown(e),b4Return2 = true;if (this.events.b4MouseDown) {b4Return2 = this.fireEvent('b4MouseDownEvent', e);}var mDownReturn = this.onMouseDown(e),mDownReturn2 = true;if (this.events.mouseDown) {if (mDownReturn === false) {//Fixes #2528759 - Mousedown function returned false, don't fire the event and cancel everything.mDownReturn2 = false;} else {mDownReturn2 = this.fireEvent('mouseDownEvent', e);}}if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) {return;}this.DDM.refreshCache(this.groups);// 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(Event.getPageX(e), Event.getPageY(e));if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {} else {if (this.clickValidator(e)) {// set the initial element positionthis.setStartPosition();// start tracking mousemove distance and mousedown time to// determine when to start the actual dragthis.DDM.handleMouseDown(e, this);// this mousedown is minethis.DDM.stopEvent(e);} else {}}},/*** @method clickValidator* @description Method validates that the clicked element* was indeed the handle or a valid child of the handle* @param {Event} e*/clickValidator: function(e) {var target = YAHOO.util.Event.getTarget(e);return ( this.isValidHandleChild(target) &&(this.id == this.handleElId ||this.DDM.handleWasClicked(target, this.id)) );},/*** 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) {var x = iPageX - this.deltaX;var y = iPageY - this.deltaY;if (this.constrainX) {if (x < this.minX) { x = this.minX; }if (x > this.maxX) { x = this.maxX; }}if (this.constrainY) {if (y < this.minY) { y = this.minY; }if (y > this.maxY) { y = this.maxY; }}x = this.getTick(x, this.xTicks);y = this.getTick(y, this.yTicks);return {x:x, y:y};},/*** 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) {var type = tagName.toUpperCase();this.invalidHandleTypes[type] = type;},/*** 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") {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) {this.invalidHandleClasses.push(cssClass);},/*** 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* @method removeInvalidHandleId* @param {string} id the id of the element to re-enable*/removeInvalidHandleId: function(id) {if (typeof id !== "string") {id = Dom.generateId(id);}delete this.invalidHandleIds[id];},/*** Unsets an invalid css class* @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<len; ++i) {if (this.invalidHandleClasses[i] == cssClass) {delete this.invalidHandleClasses[i];}}},/*** Checks the tag exclusion list to see if this click should be ignored* @method isValidHandleChild* @param {HTMLElement} node the HTMLElement to evaluate* @return {boolean} true if this is a valid tag type, false if not*/isValidHandleChild: function(node) {var valid = true;// var n = (node.nodeName == "#text") ? node.parentNode : node;var nodeName;try {nodeName = node.nodeName.toUpperCase();} catch(e) {nodeName = node.nodeName;}valid = valid && !this.invalidHandleTypes[nodeName];valid = valid && !this.invalidHandleIds[node.id];for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);}return valid;},/*** Create the array of horizontal tick marks if an interval was specified* in setXConstraint().* @method setXTicks* @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) ;},/*** Create the array of vertical tick marks if an interval was specified in* setYConstraint().* @method setYTicks* @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) ;},/*** 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* 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 = parseInt(iLeft, 10);this.rightConstraint = parseInt(iRight, 10);this.minX = this.initPageX - this.leftConstraint;this.maxX = this.initPageX + this.rightConstraint;if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }this.constrainX = true;},/*** 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;this.constrainY = false;this.clearTicks();},/*** Clears any tick interval defined for this instance* @method clearTicks*/clearTicks: function() {this.xTicks = null;this.yTicks = null;this.xTickSize = 0;this.yTickSize = 0;},/*** 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* element should move iTickSize pixels at a time.*/setYConstraint: function(iUp, iDown, iTickSize) {this.topConstraint = parseInt(iUp, 10);this.bottomConstraint = parseInt(iDown, 10);this.minY = this.initPageY - this.topConstraint;this.maxY = this.initPageY + this.bottomConstraint;if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }this.constrainY = true;},/*** resetConstraints must be called if you manually reposition a dd element.* @method resetConstraints*/resetConstraints: function() {// Maintain offsets if necessaryif (this.initPageX || this.initPageX === 0) {// figure out how much this thing has movedvar dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;this.setInitPosition(dx, dy);// This is the first time we have detected the element's position} else {this.setInitPosition();}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.* @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* @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, len=tickArray.length; i<len; ++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* @method toString* @return {string} string representation of the dd obj*/toString: function() {return ("DragDrop " + this.id);}};YAHOO.augment(YAHOO.util.DragDrop, YAHOO.util.EventProvider);/*** @event mouseDownEvent* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4MouseDownEvent* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event mouseUpEvent* @description Fired from inside DragDropMgr when the drag operation is finished.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4StartDragEvent* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event startDragEvent* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4EndDragEvent* @description Fires before the endDragEvent. Returning false will cancel.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event endDragEvent* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEvent* @description Occurs every mousemove event while dragging.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragEvent* @description Fires before the dragEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event invalidDropEvent* @description Fires when the dragged objects is dropped in a location that contains no drop targets.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOutEvent* @description Fires before the dragOutEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOutEvent* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEnterEvent* @description Occurs when the dragged object first interacts with another targettable drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOverEvent* @description Fires before the dragOverEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOverEvent* @description Fires every mousemove event while over a drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragDropEvent* @description Fires before the dragDropEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragDropEvent* @description Fires when the dragged objects is dropped on another.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*/})();/*** 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} sGroup the group of related DragDrop items* @param {object} config an object containing configurable attributes* Valid properties for DD:* scroll*/YAHOO.util.DD = function(id, sGroup, config) {if (id) {this.init(id, sGroup, config);}};YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, {/*** When set to true, the utility automatically tries to scroll the browser* window when 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* @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)* @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.* @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 positioningvar el = this.getDragEl();this.alignElWithMouse(el, iPageX, iPageY);},/*** 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.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.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);var self = this;setTimeout(function() {self.autoScroll.call(self, oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);}, 0);},/*** 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];}},/*** 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) {if (this.scroll) {// The client heightvar clientH = this.DDM.getClientHeight();// The client widthvar clientW = this.DDM.getClientWidth();// The amt scrolled downvar st = this.DDM.getScrollTop();// The amt scrolled rightvar sl = this.DDM.getScrollLeft();// Location of the bottom of the elementvar bot = h + y;// Location of the right of the elementvar right = w + x;// 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 constraintsvar toBot = (clientH + st - y - this.deltaY);// The distance from the cursor to the right of the visible areavar toRight = (clientW + sl - x - this.deltaX);// 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;// Scroll down if we are near the bottom of the visible page and the// obj extends below the creaseif ( bot > clientH && toBot < thresh ) {window.scrollTo(sl, st + scrAmt);}// Scroll up if the window is scrolled down and the top of the object// goes above the top borderif ( y < st && st > 0 && y - st < thresh ) {window.scrollTo(sl, st - scrAmt);}// 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);}// Scroll left if the window has been scrolled to the right and the obj// extends past the left borderif ( x < sl && sl > 0 && x - sl < thresh ) {window.scrollTo(sl - scrAmt, st);}}},/** 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);},/** Event that fires prior to the onMouseDown event. Overrides* YAHOO.util.DragDrop.*/b4MouseDown: function(e) {this.setStartPosition();// this.resetConstraints();this.autoOffset(YAHOO.util.Event.getPageX(e),YAHOO.util.Event.getPageY(e));},/** 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));},toString: function() {return ("DD " + this.id);}//////////////////////////////////////////////////////////////////////////// Debugging ygDragDrop events that can be overridden///////////////////////////////////////////////////////////////////////////*startDrag: function(x, y) {},onDrag: function(e) {},onDragEnter: function(e, id) {},onDragOver: function(e, id) {},onDragOut: function(e, id) {},onDragDrop: function(e, id) {},endDrag: function(e) {}*//*** @event mouseDownEvent* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4MouseDownEvent* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event mouseUpEvent* @description Fired from inside DragDropMgr when the drag operation is finished.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4StartDragEvent* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event startDragEvent* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4EndDragEvent* @description Fires before the endDragEvent. Returning false will cancel.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event endDragEvent* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEvent* @description Occurs every mousemove event while dragging.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragEvent* @description Fires before the dragEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event invalidDropEvent* @description Fires when the dragged objects is dropped in a location that contains no drop targets.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOutEvent* @description Fires before the dragOutEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOutEvent* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEnterEvent* @description Occurs when the dragged object first interacts with another targettable drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOverEvent* @description Fires before the dragOverEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOverEvent* @description Fires every mousemove event while over a drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragDropEvent* @description Fires before the dragDropEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragDropEvent* @description Fires when the dragged objects is dropped on another.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*/});/*** A DragDrop implementation that inserts an empty, bordered div into* the document that follows the cursor during drag operations. At the time of* the click, the frame div is resized to the dimensions of the linked html* element, and moved to the exact location of the linked element.** References to the "frame" element refer to the single proxy element that* 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:* resizeFrame, centerFrame, dragElId*/YAHOO.util.DDProxy = function(id, sGroup, config) {if (id) {this.init(id, sGroup, config);this.initFrame();}};/*** The default drag frame div id* @property YAHOO.util.DDProxy.dragElId* @type String* @static*/YAHOO.util.DDProxy.dragElId = "ygddfdiv";YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, {/*** 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,/*** 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,/*** Creates the proxy element if it does not yet exist* @method createFrame*/createFrame: function() {var self=this, body=document.body;if (!body || !body.firstChild) {setTimeout( function() { self.createFrame(); }, 50 );return;}var div=this.getDragEl(), Dom=YAHOO.util.Dom;if (!div) {div = document.createElement("div");div.id = this.dragElId;var s = div.style;s.position = "absolute";s.visibility = "hidden";s.cursor = "move";s.border = "2px solid #aaa";s.zIndex = 999;s.height = "25px";s.width = "25px";var _data = document.createElement('div');Dom.setStyle(_data, 'height', '100%');Dom.setStyle(_data, 'width', '100%');/*** If the proxy element has no background-color, then it is considered to the "transparent" by Internet Explorer.* Since it is "transparent" then the events pass through it to the iframe below.* So creating a "fake" div inside the proxy element and giving it a background-color, then setting it to an* opacity of 0, it appears to not be there, however IE still thinks that it is so the events never pass through.*/Dom.setStyle(_data, 'background-color', '#ccc');Dom.setStyle(_data, 'opacity', '0');div.appendChild(_data);// 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);}},/*** 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);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();if (this.centerFrame) {this.setDelta( Math.round(parseInt(s.width, 10)/2),Math.round(parseInt(s.height, 10)/2) );}this.setDragElPos(iPageX, iPageY);YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible");},/*** 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();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);DOM.setStyle( dragEl, "width", newWidth + "px" );DOM.setStyle( dragEl, "height", newHeight + "px" );}},// overrides YAHOO.util.DragDropb4MouseDown: function(e) {this.setStartPosition();var x = YAHOO.util.Event.getPageX(e);var y = YAHOO.util.Event.getPageY(e);this.autoOffset(x, y);// This causes the autoscroll code to kick off, which means autoscroll can// happen prior to the check for a valid drag handle.// this.setDragElPos(x, y);},// overrides YAHOO.util.DragDropb4StartDrag: function(x, y) {// show the drag framethis.showFrame(x, y);},// overrides YAHOO.util.DragDropb4EndDrag: function(e) {YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden");},// 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();// Show the drag frame briefly so we can get its position// del.style.visibility = "";DOM.setStyle(del, "visibility", "");// 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", "");},toString: function() {return ("DDProxy " + this.id);}/*** @event mouseDownEvent* @description Provides access to the mousedown event. The mousedown does not always result in a drag operation.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4MouseDownEvent* @description Provides access to the mousedown event, before the mouseDownEvent gets fired. Returning false will cancel the drag.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event mouseUpEvent* @description Fired from inside DragDropMgr when the drag operation is finished.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4StartDragEvent* @description Fires before the startDragEvent, returning false will cancel the startDrag Event.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event startDragEvent* @description Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4EndDragEvent* @description Fires before the endDragEvent. Returning false will cancel.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event endDragEvent* @description Fires on the mouseup event after a drag has been initiated (startDrag fired).* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEvent* @description Occurs every mousemove event while dragging.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragEvent* @description Fires before the dragEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event invalidDropEvent* @description Fires when the dragged objects is dropped in a location that contains no drop targets.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOutEvent* @description Fires before the dragOutEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOutEvent* @description Fires when a dragged object is no longer over an object that had the onDragEnter fire.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragEnterEvent* @description Occurs when the dragged object first interacts with another targettable drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragOverEvent* @description Fires before the dragOverEvent.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragOverEvent* @description Fires every mousemove event while over a drag and drop object.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event b4DragDropEvent* @description Fires before the dragDropEvent* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*//*** @event dragDropEvent* @description Fires when the dragged objects is dropped on another.* @type YAHOO.util.CustomEvent See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.*/});/*** 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.* @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*/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, {toString: function() {return ("DDTarget " + this.id);}});YAHOO.register("dragdrop", YAHOO.util.DragDropMgr, {version: "2.9.0", build: "2800"});}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-event"]});