<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js">/*
|
* This is a derivative of the similarly named class in the YUI Library.
|
* The original license:
|
* Copyright (c) 2006, Yahoo! Inc. All rights reserved.
|
* Code licensed under the BSD License:
|
* http://developer.yahoo.net/yui/license.txt
|
*/
|
|
|
<span id='Ext-dd-DragDropManager'>/**
|
</span> * DragDropManager 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.
|
*/
|
Ext.define('Ext.dd.DragDropManager', {
|
singleton: true,
|
|
requires: ['Ext.util.Region'],
|
|
uses: ['Ext.tip.QuickTipManager'],
|
|
// shorter ClassName, to save bytes and use internally
|
alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
|
|
<span id='Ext-dd-DragDropManager-property-ids'> /**
|
</span> * @property {String[]} ids
|
* Two dimensional Array of registered DragDrop objects. The first
|
* dimension is the DragDrop item group, the second the DragDrop
|
* object.
|
* @private
|
*/
|
ids: {},
|
|
<span id='Ext-dd-DragDropManager-property-handleIds'> /**
|
</span> * @property {String[]} handleIds
|
* Array of element ids defined as drag handles. Used to determine
|
* if the element that generated the mousedown event is actually the
|
* handle and not the html element itself.
|
* @private
|
*/
|
handleIds: {},
|
|
<span id='Ext-dd-DragDropManager-property-dragCurrent'> /**
|
</span> * @property {Ext.dd.DragDrop} dragCurrent
|
* the DragDrop object that is currently being dragged
|
* @private
|
*/
|
dragCurrent: null,
|
|
<span id='Ext-dd-DragDropManager-property-dragOvers'> /**
|
</span> * @property {Ext.dd.DragDrop[]} dragOvers
|
* the DragDrop object(s) that are being hovered over
|
* @private
|
*/
|
dragOvers: {},
|
|
<span id='Ext-dd-DragDropManager-property-deltaX'> /**
|
</span> * @property {Number} deltaX
|
* the X distance between the cursor and the object being dragged
|
* @private
|
*/
|
deltaX: 0,
|
|
<span id='Ext-dd-DragDropManager-property-deltaY'> /**
|
</span> * @property {Number} deltaY
|
* the Y distance between the cursor and the object being dragged
|
* @private
|
*/
|
deltaY: 0,
|
|
<span id='Ext-dd-DragDropManager-property-preventDefault'> /**
|
</span> * @property {Boolean} preventDefault
|
* 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)
|
*/
|
preventDefault: true,
|
|
<span id='Ext-dd-DragDropManager-property-stopPropagation'> /**
|
</span> * @property {Boolean} stopPropagation
|
* 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.
|
*/
|
stopPropagation: true,
|
|
<span id='Ext-dd-DragDropManager-property-initialized'> /**
|
</span> * Internal flag that is set to true when drag and drop has been
|
* intialized
|
* @property initialized
|
* @private
|
*/
|
initialized: false,
|
|
<span id='Ext-dd-DragDropManager-property-locked'> /**
|
</span> * All drag and drop can be disabled.
|
* @property locked
|
* @private
|
*/
|
locked: false,
|
|
<span id='Ext-dd-DragDropManager-method-init'> /**
|
</span> * Called the first time an element is registered.
|
* @private
|
*/
|
init: function() {
|
this.initialized = true;
|
},
|
|
<span id='Ext-dd-DragDropManager-property-POINT'> /**
|
</span> * @property {Number} POINT
|
* In point mode, drag and drop interaction is defined by the
|
* location of the cursor during the drag/drop
|
*/
|
POINT: 0,
|
|
<span id='Ext-dd-DragDropManager-property-INTERSECT'> /**
|
</span> * @property {Number} INTERSECT
|
* In intersect mode, drag and drop interaction is defined by the
|
* overlap of two or more drag and drop objects.
|
*/
|
INTERSECT: 1,
|
|
<span id='Ext-dd-DragDropManager-property-mode'> /**
|
</span> * @property {Number} mode
|
* The current drag and drop mode. Default: POINT
|
*/
|
mode: 0,
|
|
<span id='Ext-dd-DragDropManager-property-notifyOccluded'> /**
|
</span> * @property {Boolean} [notifyOccluded=false]
|
* This config is only provided to provide old, usually unwanted drag/drop behaviour.
|
*
|
* From ExtJS 4.1.0 onwards, when drop targets are contained in floating, absolutely positioned elements
|
* such as in {@link Ext.window.Window Windows}, which may overlap each other, `over` and `drop` events
|
* are only delivered to the topmost drop target at the mouse position.
|
*
|
* If all targets below that in zIndex order should also receive notifications, set
|
* `notifyOccluded` to `true`.
|
*/
|
notifyOccluded: false,
|
|
<span id='Ext-dd-DragDropManager-property-dragCls'> /**
|
</span> * @property {String} dragCls
|
* @readonly
|
* Class to add to the {@link Ext.dd.DragDrop#getDragEl dragged element} of a DragDrop instance.
|
*/
|
dragCls: Ext.baseCSSPrefix + 'dd-drag-current',
|
|
<span id='Ext-dd-DragDropManager-method-_execOnAll'> /**
|
</span> * Runs method on all drag and drop objects
|
* @private
|
*/
|
_execOnAll: function(sMethod, args) {
|
var i, j, oDD;
|
for (i in this.ids) {
|
for (j in this.ids[i]) {
|
oDD = this.ids[i][j];
|
if (! this.isTypeOfDD(oDD)) {
|
continue;
|
}
|
oDD[sMethod].apply(oDD, args);
|
}
|
}
|
},
|
|
<span id='Ext-dd-DragDropManager-method-_onLoad'> /**
|
</span> * Drag and drop initialization. Sets up the global event handlers
|
* @private
|
*/
|
_onLoad: function() {
|
|
this.init();
|
|
var Event = Ext.EventManager;
|
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);
|
|
},
|
|
<span id='Ext-dd-DragDropManager-method-_onResize'> /**
|
</span> * Reset constraints on all drag and drop objs
|
* @private
|
*/
|
_onResize: function(e) {
|
this._execOnAll("resetConstraints", []);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-lock'> /**
|
</span> * Lock all drag and drop functionality
|
*/
|
lock: function() { this.locked = true; },
|
|
<span id='Ext-dd-DragDropManager-method-unlock'> /**
|
</span> * Unlock all drag and drop functionality
|
*/
|
unlock: function() { this.locked = false; },
|
|
<span id='Ext-dd-DragDropManager-method-isLocked'> /**
|
</span> * Is drag and drop locked?
|
* @return {Boolean} True if drag and drop is locked, false otherwise.
|
*/
|
isLocked: function() { return this.locked; },
|
|
<span id='Ext-dd-DragDropManager-property-locationCache'> /**
|
</span> * @property {Object} locationCache
|
* Location cache that is set for all drag drop objects when a drag is
|
* initiated, cleared when the drag is finished.
|
* @private
|
*/
|
locationCache: {},
|
|
<span id='Ext-dd-DragDropManager-property-useCache'> /**
|
</span> * @property {Boolean} useCache
|
* Set useCache to false if you want to force object the lookup of each
|
* drag and drop linked element constantly during a drag.
|
*/
|
useCache: true,
|
|
<span id='Ext-dd-DragDropManager-property-clickPixelThresh'> /**
|
</span> * @property {Number} clickPixelThresh
|
* The number of pixels that the mouse needs to move after the
|
* mousedown before the drag is initiated. Default=3;
|
*/
|
clickPixelThresh: 3,
|
|
<span id='Ext-dd-DragDropManager-property-clickTimeThresh'> /**
|
</span> * @property {Number} clickTimeThresh
|
* The number of milliseconds after the mousedown event to initiate the
|
* drag if we don't get a mouseup event. Default=350
|
*/
|
clickTimeThresh: 350,
|
|
<span id='Ext-dd-DragDropManager-property-dragThreshMet'> /**
|
</span> * @property {Boolean} dragThreshMet
|
* Flag that indicates that either the drag pixel threshold or the
|
* mousdown time threshold has been met
|
* @private
|
*/
|
dragThreshMet: false,
|
|
<span id='Ext-dd-DragDropManager-property-clickTimeout'> /**
|
</span> * @property {Object} clickTimeout
|
* Timeout used for the click time threshold
|
* @private
|
*/
|
clickTimeout: null,
|
|
<span id='Ext-dd-DragDropManager-property-startX'> /**
|
</span> * @property {Number} startX
|
* The X position of the mousedown event stored for later use when a
|
* drag threshold is met.
|
* @private
|
*/
|
startX: 0,
|
|
<span id='Ext-dd-DragDropManager-property-startY'> /**
|
</span> * @property {Number} startY
|
* The Y position of the mousedown event stored for later use when a
|
* drag threshold is met.
|
* @private
|
*/
|
startY: 0,
|
|
<span id='Ext-dd-DragDropManager-method-regDragDrop'> /**
|
</span> * Each DragDrop instance must be registered with the DragDropManager.
|
* This is executed in DragDrop.init()
|
* @param {Ext.dd.DragDrop} oDD the DragDrop object to register
|
* @param {String} sGroup the name of the group this element belongs to
|
*/
|
regDragDrop: function(oDD, sGroup) {
|
if (!this.initialized) { this.init(); }
|
|
if (!this.ids[sGroup]) {
|
this.ids[sGroup] = {};
|
}
|
this.ids[sGroup][oDD.id] = oDD;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-removeDDFromGroup'> /**
|
</span> * Removes the supplied dd instance from the supplied group. Executed
|
* by DragDrop.removeFromGroup, so don't call this function directly.
|
* @private
|
*/
|
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];
|
}
|
},
|
|
<span id='Ext-dd-DragDropManager-method-_remove'> /**
|
</span> * Unregisters a drag and drop item. This is executed in
|
* DragDrop.unreg, use that method instead of calling this directly.
|
* @private
|
*/
|
_remove: function(oDD) {
|
for (var g in oDD.groups) {
|
if (g && this.ids[g] && this.ids[g][oDD.id]) {
|
delete this.ids[g][oDD.id];
|
}
|
}
|
delete this.handleIds[oDD.id];
|
},
|
|
<span id='Ext-dd-DragDropManager-method-regHandle'> /**
|
</span> * Each DragDrop handle element must be registered. This is done
|
* automatically when executing DragDrop.setHandleElId()
|
* @param {String} sDDId the DragDrop id this element is a handle for
|
* @param {String} sHandleId the id of the element that is the drag
|
* handle
|
*/
|
regHandle: function(sDDId, sHandleId) {
|
if (!this.handleIds[sDDId]) {
|
this.handleIds[sDDId] = {};
|
}
|
this.handleIds[sDDId][sHandleId] = sHandleId;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-isDragDrop'> /**
|
</span> * Utility function to determine if a given element has been
|
* registered as a drag drop item.
|
* @param {String} id the element id to check
|
* @return {Boolean} true if this element is a DragDrop item,
|
* false otherwise
|
*/
|
isDragDrop: function(id) {
|
return ( this.getDDById(id) ) ? true : false;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getRelated'> /**
|
</span> * Returns the drag and drop instances that are in all groups the
|
* passed in instance belongs to.
|
* @param {Ext.dd.DragDrop} p_oDD the obj to get related data for
|
* @param {Boolean} bTargetsOnly if true, only return targetable objs
|
* @return {Ext.dd.DragDrop[]} the related instances
|
*/
|
getRelated: function(p_oDD, bTargetsOnly) {
|
var oDDs = [],
|
i, j, dd;
|
for (i in p_oDD.groups) {
|
for (j in this.ids[i]) {
|
dd = this.ids[i][j];
|
if (! this.isTypeOfDD(dd)) {
|
continue;
|
}
|
if (!bTargetsOnly || dd.isTarget) {
|
oDDs[oDDs.length] = dd;
|
}
|
}
|
}
|
|
return oDDs;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-isLegalTarget'> /**
|
</span> * Returns true if the specified dd target is a legal target for
|
* the specifice drag obj
|
* @param {Ext.dd.DragDrop} oDD the drag obj
|
* @param {Ext.dd.DragDrop} oTargetDD the target
|
* @return {Boolean} true if the target is a legal target for the
|
* dd obj
|
*/
|
isLegalTarget: function (oDD, oTargetDD) {
|
var targets = this.getRelated(oDD, true),
|
i, len;
|
for (i=0, len=targets.length;i<len;++i) {
|
if (targets[i].id == oTargetDD.id) {
|
return true;
|
}
|
}
|
|
return false;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-isTypeOfDD'> /**
|
</span> * 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.
|
* @param {Object} the object to evaluate
|
* @return {Boolean} true if typeof oDD = DragDrop
|
*/
|
isTypeOfDD: function (oDD) {
|
return (oDD && oDD.__ygDragDrop);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-isHandle'> /**
|
</span> * Utility function to determine if a given element has been
|
* registered as a drag drop handle for the given Drag Drop object.
|
* @param {String} id the element id to check
|
* @return {Boolean} true if this element is a DragDrop handle, false
|
* otherwise
|
*/
|
isHandle: function(sDDId, sHandleId) {
|
return ( this.handleIds[sDDId] &&
|
this.handleIds[sDDId][sHandleId] );
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getDDById'> /**
|
</span> * Returns the DragDrop instance for a given id
|
* @param {String} id the id of the DragDrop object
|
* @return {Ext.dd.DragDrop} the drag drop object, null if it is not found
|
*/
|
getDDById: function(id) {
|
var i, dd;
|
for (i in this.ids) {
|
dd = this.ids[i][id];
|
if (dd instanceof Ext.dd.DDTarget) {
|
return dd;
|
}
|
}
|
return null;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-handleMouseDown'> /**
|
</span> * Fired after a registered DragDrop object gets the mousedown event.
|
* Sets up the events required to track the object being dragged
|
* @param {Event} e the event
|
* @param {Ext.dd.DragDrop} oDD the DragDrop object being dragged
|
* @private
|
*/
|
handleMouseDown: function(e, oDD) {
|
var me = this,
|
el;
|
|
if (Ext.quickTipsActive){
|
Ext.tip.QuickTipManager.ddDisable();
|
}
|
if (me.dragCurrent){
|
// the original browser mouseup wasn't handled (e.g. outside FF browser window)
|
// so clean up first to avoid breaking the next drag
|
me.handleMouseUp(e);
|
}
|
|
me.currentTarget = e.getTarget();
|
me.dragCurrent = oDD;
|
|
el = oDD.getEl();
|
|
// We use this to handle an issue where a mouseup will not be detected
|
// if the mouseup event happens outside of the browser window. When the
|
// mouse comes back, any drag will still be active
|
// http://msdn.microsoft.com/en-us/library/ms537630(VS.85).aspx
|
if (Ext.isIE9m && el.setCapture) {
|
el.setCapture();
|
}
|
|
// track start position
|
me.startX = e.getPageX();
|
me.startY = e.getPageY();
|
|
me.deltaX = me.startX - el.offsetLeft;
|
me.deltaY = me.startY - el.offsetTop;
|
|
me.dragThreshMet = false;
|
|
me.clickTimeout = setTimeout(
|
function() {
|
me.startDrag(me.startX, me.startY);
|
},
|
me.clickTimeThresh
|
);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-startDrag'> /**
|
</span> * Fired when either the drag pixel threshold or the mousedown hold
|
* time threshold has been met.
|
* @param {Number} x the X position of the original mousedown
|
* @param {Number} y the Y position of the original mousedown
|
*/
|
startDrag: function(x, y) {
|
var me = this,
|
current = me.dragCurrent,
|
dragEl;
|
|
clearTimeout(me.clickTimeout);
|
if (current) {
|
current.b4StartDrag(x, y);
|
current.startDrag(x, y);
|
dragEl = current.getDragEl();
|
|
// Add current drag class to dragged element
|
if (dragEl) {
|
Ext.fly(dragEl).addCls(me.dragCls);
|
}
|
}
|
me.dragThreshMet = true;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-handleMouseUp'> /**
|
</span> * Internal function to handle the mouseup event. Will be invoked
|
* from the context of the document.
|
* @param {Event} e the event
|
* @private
|
*/
|
handleMouseUp: function(e) {
|
var me = this;
|
|
if (Ext.quickTipsActive){
|
Ext.tip.QuickTipManager.ddEnable();
|
}
|
if (!me.dragCurrent) {
|
return;
|
}
|
|
// See setCapture call in handleMouseDown
|
if (Ext.isIE && document.releaseCapture) {
|
document.releaseCapture();
|
}
|
|
clearTimeout(me.clickTimeout);
|
|
if (me.dragThreshMet) {
|
me.fireEvents(e, true);
|
}
|
|
me.stopDrag(e);
|
|
me.stopEvent(e);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-stopEvent'> /**
|
</span> * Utility to stop event propagation and event default, if these
|
* features are turned on.
|
* @param {Event} e the event as returned by this.getEvent()
|
*/
|
stopEvent: function(e) {
|
if (this.stopPropagation) {
|
e.stopPropagation();
|
}
|
|
if (this.preventDefault) {
|
e.preventDefault();
|
}
|
},
|
|
<span id='Ext-dd-DragDropManager-method-stopDrag'> /**
|
</span> * Internal function to clean up event handlers after the drag
|
* operation is complete
|
* @param {Event} e the event
|
* @private
|
*/
|
stopDrag: function(e) {
|
var me = this,
|
current = me.dragCurrent,
|
dragEl;
|
|
// Fire the drag end event for the item that was dragged
|
if (current) {
|
if (me.dragThreshMet) {
|
|
// Remove current drag class from dragged element
|
dragEl = current.getDragEl();
|
if (dragEl) {
|
Ext.fly(dragEl).removeCls(me.dragCls);
|
}
|
|
current.b4EndDrag(e);
|
current.endDrag(e);
|
}
|
|
me.dragCurrent.onMouseUp(e);
|
}
|
|
me.dragCurrent = null;
|
me.dragOvers = {};
|
},
|
|
<span id='Ext-dd-DragDropManager-method-handleMouseMove'> /**
|
</span> * 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.
|
*
|
* @param {Event} e the event
|
* @private
|
*/
|
handleMouseMove: function(e) {
|
var me = this,
|
current = me.dragCurrent,
|
diffX,
|
diffY;
|
|
if (!current) {
|
return true;
|
}
|
|
if (!me.dragThreshMet) {
|
diffX = Math.abs(me.startX - e.getPageX());
|
diffY = Math.abs(me.startY - e.getPageY());
|
if (diffX > me.clickPixelThresh || diffY > me.clickPixelThresh) {
|
me.startDrag(me.startX, me.startY);
|
}
|
}
|
|
if (me.dragThreshMet) {
|
current.b4Drag(e);
|
current.onDrag(e);
|
if (!current.moveOnly) {
|
me.fireEvents(e, false);
|
}
|
}
|
|
me.stopEvent(e);
|
|
return true;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-fireEvents'> /**
|
</span> * Iterates over all of the DragDrop elements to find ones we are
|
* hovering over or dropping on
|
* @param {Event} e the event
|
* @param {Boolean} isDrop is this a drop op or a mouseover op?
|
* @private
|
*/
|
fireEvents: function(e, isDrop) {
|
var me = this,
|
dragCurrent = me.dragCurrent,
|
dragEl,
|
oldDragElTop,
|
mousePoint = e.getPoint(),
|
overTarget,
|
overTargetEl,
|
allTargets = [],
|
oldOvers = [], // cache the previous dragOver array
|
outEvts = [],
|
overEvts = [],
|
dropEvts = [],
|
enterEvts = [],
|
xy,
|
needsSort,
|
i,
|
len,
|
sGroup;
|
|
// If the user did the mouse up outside of the window, we could
|
// get here even though we have ended the drag.
|
if (!dragCurrent || dragCurrent.isLocked()) {
|
return;
|
}
|
|
// If we need to use the current mousemove target to find the over el,
|
// but pointer-events is not supported, AND the delta position does not place the mouse outside of the dragEl,
|
// temporarily move the dragEl away, and fake the mousemove target by using document.elementFromPoint
|
// while it's out of the way.
|
// The pointer events implementation is bugged in IE9/10 and opera, so fallback even if they report that they support it.
|
// IE8m do not support it so they will auto fall back
|
if (!me.notifyOccluded && (!Ext.supports.PointerEvents || Ext.isIE10m || Ext.isOpera) && !(dragCurrent.deltaX < 0 || dragCurrent.deltaY < 0)) {
|
dragEl = dragCurrent.getDragEl();
|
oldDragElTop = dragEl.style.top;
|
dragEl.style.top = '-10000px';
|
xy = e.getXY();
|
e.target = document.elementFromPoint(xy[0], xy[1]);
|
dragEl.style.top = oldDragElTop;
|
}
|
|
// Check to see if the object(s) we were hovering over is no longer
|
// being hovered over so we can fire the onDragOut event
|
for (i in me.dragOvers) {
|
|
overTarget = me.dragOvers[i];
|
|
if (!me.isTypeOfDD(overTarget)) {
|
continue;
|
}
|
|
// If notifyOccluded set, we use mouse position
|
if (me.notifyOccluded) {
|
if (!this.isOverTarget(mousePoint, overTarget, me.mode)) {
|
outEvts.push(overTarget);
|
}
|
}
|
// Otherwise we use event source of the mousemove event
|
else {
|
if (!e.within(overTarget.getEl())) {
|
outEvts.push(overTarget);
|
}
|
}
|
|
oldOvers[i] = true;
|
delete me.dragOvers[i];
|
}
|
|
// Collect all targets which are members of the same ddGoups that the dragCurrent is a member of, and which may recieve mouseover and drop notifications.
|
// This is preparatory to seeing which one(s) we are currently over
|
// Begin by iterating through the ddGroups of which the dragCurrent is a member
|
for (sGroup in dragCurrent.groups) {
|
|
if ("string" != typeof sGroup) {
|
continue;
|
}
|
|
// Loop over the registered members of each group, testing each as a potential target
|
for (i in me.ids[sGroup]) {
|
overTarget = me.ids[sGroup][i];
|
|
// The target is valid if it is a DD type
|
// And it's got a DOM element
|
// And it's configured to be a drop target
|
// And it's not locked
|
// And the DOM element is fully visible with no hidden ancestors
|
// And it's either not the dragCurrent, or, if it is, tha dragCurrent is configured to not ignore itself.
|
if (me.isTypeOfDD(overTarget) &&
|
(overTargetEl = overTarget.getEl()) &&
|
(overTarget.isTarget) &&
|
(!overTarget.isLocked()) &&
|
(Ext.fly(overTargetEl).isVisible(true)) &&
|
((overTarget != dragCurrent) || (dragCurrent.ignoreSelf === false))) {
|
|
// If notifyOccluded set, we use mouse position
|
if (me.notifyOccluded) {
|
|
// Only sort by zIndex if there were some which had a floating zIndex value
|
if ((overTarget.zIndex = me.getZIndex(overTargetEl)) !== -1) {
|
needsSort = true;
|
}
|
allTargets.push(overTarget);
|
}
|
// Otherwise we use event source of the mousemove event
|
else {
|
if (e.within(overTarget.getEl())) {
|
allTargets.push(overTarget);
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
// If there were floating targets, sort the highest zIndex to the top
|
if (needsSort) {
|
Ext.Array.sort(allTargets, me.byZIndex);
|
}
|
|
// Loop through possible targets, notifying the one(s) we are over.
|
// Usually we only deliver events to the topmost.
|
for (i = 0, len = allTargets.length; i < len; i++) {
|
overTarget = allTargets[i];
|
|
// If we are over the overTarget, queue it up to recieve an event of whatever type we are handling
|
if (me.isOverTarget(mousePoint, overTarget, me.mode)) {
|
// look for drop interactions
|
if (isDrop) {
|
dropEvts.push( overTarget );
|
// look for drag enter and drag over interactions
|
} else {
|
|
// initial drag over: dragEnter fires
|
if (!oldOvers[overTarget.id]) {
|
enterEvts.push( overTarget );
|
// subsequent drag overs: dragOver fires
|
} else {
|
overEvts.push( overTarget );
|
}
|
me.dragOvers[overTarget.id] = overTarget;
|
}
|
|
// Unless this DragDropManager has been explicitly configured to deliver events to multiple targets, then we are done.
|
if (!me.notifyOccluded) {
|
break;
|
}
|
}
|
}
|
|
if (me.mode) {
|
if (outEvts.length) {
|
dragCurrent.b4DragOut(e, outEvts);
|
dragCurrent.onDragOut(e, outEvts);
|
}
|
|
if (enterEvts.length) {
|
dragCurrent.onDragEnter(e, enterEvts);
|
}
|
|
if (overEvts.length) {
|
dragCurrent.b4DragOver(e, overEvts);
|
dragCurrent.onDragOver(e, overEvts);
|
}
|
|
if (dropEvts.length) {
|
dragCurrent.b4DragDrop(e, dropEvts);
|
dragCurrent.onDragDrop(e, dropEvts);
|
}
|
|
} else {
|
// fire dragout events
|
for (i=0, len=outEvts.length; i<len; ++i) {
|
dragCurrent.b4DragOut(e, outEvts[i].id);
|
dragCurrent.onDragOut(e, outEvts[i].id);
|
}
|
|
// fire enter events
|
for (i=0,len=enterEvts.length; i<len; ++i) {
|
// dc.b4DragEnter(e, oDD.id);
|
dragCurrent.onDragEnter(e, enterEvts[i].id);
|
}
|
|
// fire over events
|
for (i=0,len=overEvts.length; i<len; ++i) {
|
dragCurrent.b4DragOver(e, overEvts[i].id);
|
dragCurrent.onDragOver(e, overEvts[i].id);
|
}
|
|
// fire drop events
|
for (i=0, len=dropEvts.length; i<len; ++i) {
|
dragCurrent.b4DragDrop(e, dropEvts[i].id);
|
dragCurrent.onDragDrop(e, dropEvts[i].id);
|
}
|
|
}
|
|
// notify about a drop that did not find a target
|
if (isDrop && !dropEvts.length) {
|
dragCurrent.onInvalidDrop(e);
|
}
|
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getZIndex'> /**
|
</span> * @private
|
* Collects the z-index of the passed element, looking up the parentNode axis to find an absolutely positioned ancestor
|
* which is able to yield a z-index. If found to be not absolutely positionedm returns -1.
|
*
|
* This is used when sorting potential drop targets into z-index order so that only the topmost receives `over` and `drop` events.
|
*
|
* @return {Number} The z-index of the element, or of its topmost absolutely positioned ancestor. Returns -1 if the element is not
|
* absolutely positioned.
|
*/
|
getZIndex: function(element) {
|
var body = document.body,
|
z,
|
zIndex = -1;
|
|
element = Ext.getDom(element);
|
while (element !== body) {
|
if (!isNaN(z = Number(Ext.fly(element).getStyle('zIndex')))) {
|
zIndex = z;
|
}
|
element = element.parentNode;
|
}
|
return zIndex;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-byZIndex'> /**
|
</span> * @private
|
* Utility method to pass to {@link Ext.Array#sort} when sorting potential drop targets by z-index.
|
*/
|
byZIndex: function(d1, d2) {
|
return d1.zIndex < d2.zIndex;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getBestMatch'> /**
|
</span> * 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.
|
* @param {Ext.dd.DragDrop[]} dds The array of drag and drop objects
|
* targeted
|
* @return {Ext.dd.DragDrop} The best single match
|
*/
|
getBestMatch: function(dds) {
|
var winner = null,
|
len = dds.length,
|
i, dd;
|
// Return null if the input is not what we expect
|
//if (!dds || !dds.length || dds.length == 0) {
|
// winner = null;
|
// If there is only one item, it wins
|
//} else if (dds.length == 1) {
|
|
|
if (len == 1) {
|
winner = dds[0];
|
} else {
|
// Loop through the targeted items
|
for (i=0; i<len; ++i) {
|
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 (dd.cursorIsOver) {
|
winner = dd;
|
break;
|
// Otherwise the object with the most overlap wins
|
} else {
|
if (!winner ||
|
winner.overlap.getArea() < dd.overlap.getArea()) {
|
winner = dd;
|
}
|
}
|
}
|
}
|
|
return winner;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-refreshCache'> /**
|
</span> * 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:
|
*
|
* Ext.dd.DragDropManager.refreshCache(ddinstance.groups);
|
*
|
* Alternatively:
|
*
|
* Ext.dd.DragDropManager.refreshCache({group1:true, group2:true});
|
*
|
* TODO: this really should be an indexed array. Alternatively this
|
* method could accept both.
|
*
|
* @param {Object} groups an associative array of groups to refresh
|
*/
|
refreshCache: function(groups) {
|
var sGroup, i, oDD, loc;
|
for (sGroup in groups) {
|
if ("string" != typeof sGroup) {
|
continue;
|
}
|
for (i in this.ids[sGroup]) {
|
oDD = this.ids[sGroup][i];
|
|
if (this.isTypeOfDD(oDD)) {
|
// if (this.isTypeOfDD(oDD) && oDD.isTarget) {
|
loc = this.getLocation(oDD);
|
if (loc) {
|
this.locationCache[oDD.id] = loc;
|
} else {
|
delete this.locationCache[oDD.id];
|
// this will unregister the drag and drop object if
|
// the element is not in a usable state
|
// oDD.unreg();
|
}
|
}
|
}
|
}
|
},
|
|
<span id='Ext-dd-DragDropManager-method-verifyEl'> /**
|
</span> * 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
|
* @param {HTMLElement} el the element to check
|
* @return {Boolean} true if the element looks usable
|
*/
|
verifyEl: function(el) {
|
if (el) {
|
var parent;
|
if(Ext.isIE){
|
try{
|
parent = el.offsetParent;
|
}catch(e){}
|
}else{
|
parent = el.offsetParent;
|
}
|
if (parent) {
|
return true;
|
}
|
}
|
|
return false;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getLocation'> /**
|
</span> * Returns a Region object containing the drag and drop element's position
|
* and size, including the padding configured for it
|
* @param {Ext.dd.DragDrop} oDD the drag and drop object to get the location for.
|
* @return {Ext.util.Region} a Region object representing the total area
|
* the element occupies, including any padding
|
* the instance is configured for.
|
*/
|
getLocation: function(oDD) {
|
if (! this.isTypeOfDD(oDD)) {
|
return null;
|
}
|
|
//delegate getLocation method to the
|
//drag and drop target.
|
if (oDD.getRegion) {
|
return oDD.getRegion();
|
}
|
|
var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
|
|
try {
|
pos= Ext.Element.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 Ext.util.Region(t, r, b, l);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-isOverTarget'> /**
|
</span> * Checks the cursor location to see if it over the target
|
* @param {Ext.util.Point} pt The point to evaluate
|
* @param {Ext.dd.DragDrop} oTarget the DragDrop object we are inspecting
|
* @return {Boolean} true if the mouse is over the target
|
* @private
|
*/
|
isOverTarget: function(pt, oTarget, intersect) {
|
// use cache if available
|
var loc = this.locationCache[oTarget.id],
|
dc,
|
pos,
|
el,
|
curRegion,
|
overlap;
|
|
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 also done. Otherwise we need to evaluate the
|
// location of the target as related to the actual location of the
|
// dragged element.
|
dc = this.dragCurrent;
|
if (!dc || !dc.getTargetCoord ||
|
(!intersect && !dc.constrainX && !dc.constrainY)) {
|
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.
|
pos = dc.getTargetCoord(pt.x, pt.y);
|
|
el = dc.getDragEl();
|
curRegion = new Ext.util.Region(pos.y,
|
pos.x + el.offsetWidth,
|
pos.y + el.offsetHeight,
|
pos.x
|
);
|
|
overlap = curRegion.intersect(loc);
|
|
if (overlap) {
|
oTarget.overlap = overlap;
|
return (intersect) ? true : oTarget.cursorIsOver;
|
} else {
|
return false;
|
}
|
},
|
|
<span id='Ext-dd-DragDropManager-method-_onUnload'> /**
|
</span> * unload event handler
|
* @private
|
*/
|
_onUnload: function(e, me) {
|
Ext.dd.DragDropManager.unregAll();
|
},
|
|
<span id='Ext-dd-DragDropManager-method-unregAll'> /**
|
</span> * Cleans up the drag and drop events and objects.
|
* @private
|
*/
|
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 = {};
|
},
|
|
<span id='Ext-dd-DragDropManager-property-elementCache'> /**
|
</span> * @property {Object} elementCache
|
* A cache of DOM elements
|
* @private
|
*/
|
elementCache: {},
|
|
<span id='Ext-dd-DragDropManager-method-getElWrapper'> /**
|
</span> * Get the wrapper for the DOM element specified
|
* @param {String} id the id of the element to get
|
* @return {Ext.dd.DragDropManager.ElementWrapper} the wrapped element
|
* @private
|
* @deprecated This wrapper isn't that useful
|
*/
|
getElWrapper: function(id) {
|
var oWrapper = this.elementCache[id];
|
if (!oWrapper || !oWrapper.el) {
|
oWrapper = this.elementCache[id] =
|
new this.ElementWrapper(Ext.getDom(id));
|
}
|
return oWrapper;
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getElement'> /**
|
</span> * Returns the actual DOM element
|
* @param {String} id the id of the elment to get
|
* @return {Object} The element
|
* @deprecated use Ext.lib.Ext.getDom instead
|
*/
|
getElement: function(id) {
|
return Ext.getDom(id);
|
},
|
|
<span id='Ext-dd-DragDropManager-method-getCss'> /**
|
</span> * Returns the style property for the DOM element (i.e.,
|
* document.getElById(id).style)
|
* @param {String} id the id of the elment to get
|
* @return {Object} The style property of the element
|
*/
|
getCss: function(id) {
|
var el = Ext.getDom(id);
|
return (el) ? el.style : null;
|
},
|
|
<span id='Ext-dd-DragDropManager-ElementWrapper'> /**
|
</span> * @class Ext.dd.DragDropManager.ElementWrapper
|
* Deprecated inner class for cached elements.
|
* @private
|
* @deprecated This wrapper isn't that useful
|
*/
|
ElementWrapper: function(el) {
|
<span id='Ext-dd-DragDropManager-ElementWrapper-property-el'> /** The element */
|
</span> this.el = el || null;
|
<span id='Ext-dd-DragDropManager-ElementWrapper-property-id'> /** The element id */
|
</span> this.id = this.el && el.id;
|
<span id='Ext-dd-DragDropManager-ElementWrapper-property-css'> /** A reference to the style property */
|
</span> this.css = this.el && el.style;
|
},
|
|
// Continue class docs
|
<span id='Ext-dd-DragDropElement'> /** @class Ext.dd.DragDropElement */
|
</span>
|
<span id='Ext-dd-DragDropElement-method-getPosX'> /**
|
</span> * Returns the X position of an html element
|
* @param {HTMLElement} el the element for which to get the position
|
* @return {Number} the X coordinate
|
*/
|
getPosX: function(el) {
|
return Ext.Element.getX(el);
|
},
|
|
<span id='Ext-dd-DragDropElement-method-getPosY'> /**
|
</span> * Returns the Y position of an html element
|
* @param {HTMLElement} el the element for which to get the position
|
* @return {Number} the Y coordinate
|
*/
|
getPosY: function(el) {
|
return Ext.Element.getY(el);
|
},
|
|
<span id='Ext-dd-DragDropElement-method-swapNode'> /**
|
</span> * Swap two nodes. In IE, we use the native method, for others we
|
* emulate the IE behavior
|
* @param {HTMLElement} n1 the first node to swap
|
* @param {HTMLElement} n2 the other node to swap
|
*/
|
swapNode: function(n1, n2) {
|
if (n1.swapNode) {
|
n1.swapNode(n2);
|
} else {
|
var p = n2.parentNode,
|
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);
|
}
|
}
|
},
|
|
<span id='Ext-dd-DragDropElement-method-getScroll'> /**
|
</span> * Returns the current scroll position
|
* @private
|
*/
|
getScroll: function () {
|
var doc = window.document,
|
docEl = doc.documentElement,
|
body = doc.body,
|
top = 0,
|
left = 0;
|
|
if (Ext.isGecko4) {
|
top = window.scrollYOffset;
|
left = window.scrollXOffset;
|
} else {
|
if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
|
top = docEl.scrollTop;
|
left = docEl.scrollLeft;
|
} else if (body) {
|
top = body.scrollTop;
|
left = body.scrollLeft;
|
}
|
}
|
return {
|
top: top,
|
left: left
|
};
|
},
|
|
<span id='Ext-dd-DragDropElement-method-getStyle'> /**
|
</span> * Returns the specified element style property
|
* @param {HTMLElement} el the element
|
* @param {String} styleProp the style property
|
* @return {String} The value of the style property
|
*/
|
getStyle: function(el, styleProp) {
|
return Ext.fly(el).getStyle(styleProp);
|
},
|
|
<span id='Ext-dd-DragDropElement-method-getScrollTop'> /**
|
</span> * Gets the scrollTop
|
* @return {Number} the document's scrollTop
|
*/
|
getScrollTop: function () {
|
return this.getScroll().top;
|
},
|
|
<span id='Ext-dd-DragDropElement-method-getScrollLeft'> /**
|
</span> * Gets the scrollLeft
|
* @return {Number} the document's scrollTop
|
*/
|
getScrollLeft: function () {
|
return this.getScroll().left;
|
},
|
|
<span id='Ext-dd-DragDropElement-method-moveToEl'> /**
|
</span> * Sets the x/y position of an element to the location of the
|
* target element.
|
* @param {HTMLElement} moveEl The element to move
|
* @param {HTMLElement} targetEl The position reference element
|
*/
|
moveToEl: function (moveEl, targetEl) {
|
var aCoord = Ext.Element.getXY(targetEl);
|
Ext.Element.setXY(moveEl, aCoord);
|
},
|
|
<span id='Ext-dd-DragDropElement-method-numericSort'> /**
|
</span> * Numeric array sort function
|
* @param {Number} a
|
* @param {Number} b
|
* @returns {Number} positive, negative or 0
|
*/
|
numericSort: function(a, b) {
|
return (a - b);
|
},
|
|
<span id='Ext-dd-DragDropElement-property-_timeoutCount'> /**
|
</span> * @property {Number} _timeoutCount
|
* Internal counter
|
* @private
|
*/
|
_timeoutCount: 0,
|
|
<span id='Ext-dd-DragDropElement-method-_addListeners'> /**
|
</span> * Trying to make the load order less important. Without this we get
|
* an error if this file is loaded before the Event Utility.
|
* @private
|
*/
|
_addListeners: function() {
|
if ( document ) {
|
this._onLoad();
|
} else {
|
if (this._timeoutCount <= 2000) {
|
setTimeout(this._addListeners, 10);
|
if (document && document.body) {
|
this._timeoutCount += 1;
|
}
|
}
|
}
|
},
|
|
<span id='Ext-dd-DragDropElement-method-handleWasClicked'> /**
|
</span> * Recursively searches the immediate parent and all child nodes for
|
* the handle element in order to determine wheter or not it was
|
* clicked.
|
* @param {HTMLElement} node the html element to inspect
|
*/
|
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 want
|
var p = node.parentNode;
|
|
while (p) {
|
if (this.isHandle(id, p.id)) {
|
return true;
|
} else {
|
p = p.parentNode;
|
}
|
}
|
}
|
|
return false;
|
}
|
}, function() {
|
this._addListeners();
|
});
|
</pre>
|
</body>
|
</html>
|