-<html>\r
-<head>\r
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> \r
- <title>The source code</title>\r
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
-</head>\r
-<body onload="prettyPrint();">\r
- <pre class="prettyprint lang-js"><div id="cls-Ext.dd.DragTracker"></div>/**\r
- * @class Ext.dd.DragTracker\r
- * @extends Ext.util.Observable\r
- */\r
-Ext.dd.DragTracker = Ext.extend(Ext.util.Observable, {\r
- <div id="cfg-Ext.dd.DragTracker-active"></div>/**\r
- * @cfg {Boolean} active\r
- * Defaults to <tt>false</tt>.\r
- */ \r
- active: false,\r
- <div id="cfg-Ext.dd.DragTracker-tolerance"></div>/**\r
- * @cfg {Number} tolerance\r
- * Defaults to <tt>5</tt>.\r
- */ \r
- tolerance: 5,\r
- <div id="cfg-Ext.dd.DragTracker-autoStart"></div>/**\r
- * @cfg {Boolean/Number} autoStart\r
- * Defaults to <tt>false</tt>. Specify <tt>true</tt> to defer trigger start by 1000 ms.\r
- * Specify a Number for the number of milliseconds to defer trigger start.\r
- */ \r
- autoStart: false,\r
- \r
- constructor : function(config){\r
- Ext.apply(this, config);\r
- this.addEvents(\r
- <div id="event-Ext.dd.DragTracker-mousedown"></div>/**\r
- * @event mousedown\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mousedown',\r
- <div id="event-Ext.dd.DragTracker-mouseup"></div>/**\r
- * @event mouseup\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mouseup',\r
- <div id="event-Ext.dd.DragTracker-mousemove"></div>/**\r
- * @event mousemove\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mousemove',\r
- <div id="event-Ext.dd.DragTracker-dragstart"></div>/**\r
- * @event dragstart\r
- * @param {Object} this\r
- * @param {Object} startXY the page coordinates of the event\r
- */\r
- 'dragstart',\r
- <div id="event-Ext.dd.DragTracker-dragend"></div>/**\r
- * @event dragend\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'dragend',\r
- <div id="event-Ext.dd.DragTracker-drag"></div>/**\r
- * @event drag\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'drag'\r
- );\r
- \r
- this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
- \r
- if(this.el){\r
- this.initEl(this.el);\r
- }\r
- Ext.dd.DragTracker.superclass.constructor.call(this, config);\r
- },\r
-\r
- initEl: function(el){\r
- this.el = Ext.get(el);\r
- el.on('mousedown', this.onMouseDown, this,\r
- this.delegate ? {delegate: this.delegate} : undefined);\r
- },\r
-\r
- destroy : function(){\r
- this.el.un('mousedown', this.onMouseDown, this);\r
- },\r
-\r
- onMouseDown: function(e, target){\r
- if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){\r
- this.startXY = this.lastXY = e.getXY();\r
- this.dragTarget = this.delegate ? target : this.el.dom;\r
- if(this.preventDefault !== false){\r
- e.preventDefault();\r
- }\r
- var doc = Ext.getDoc();\r
- doc.on('mouseup', this.onMouseUp, this);\r
- doc.on('mousemove', this.onMouseMove, this);\r
- doc.on('selectstart', this.stopSelect, this);\r
- if(this.autoStart){\r
- this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);\r
- }\r
- }\r
- },\r
-\r
- onMouseMove: function(e, target){\r
- // HACK: IE hack to see if button was released outside of window. */\r
- if(this.active && Ext.isIE && !e.browserEvent.button){\r
- e.preventDefault();\r
- this.onMouseUp(e);\r
- return;\r
- }\r
-\r
- e.preventDefault();\r
- var xy = e.getXY(), s = this.startXY;\r
- this.lastXY = xy;\r
- if(!this.active){\r
- if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){\r
- this.triggerStart();\r
- }else{\r
- return;\r
- }\r
- }\r
- this.fireEvent('mousemove', this, e);\r
- this.onDrag(e);\r
- this.fireEvent('drag', this, e);\r
- },\r
-\r
- onMouseUp: function(e){\r
- var doc = Ext.getDoc();\r
- doc.un('mousemove', this.onMouseMove, this);\r
- doc.un('mouseup', this.onMouseUp, this);\r
- doc.un('selectstart', this.stopSelect, this);\r
- e.preventDefault();\r
- this.clearStart();\r
- var wasActive = this.active;\r
- this.active = false;\r
- delete this.elRegion;\r
- this.fireEvent('mouseup', this, e);\r
- if(wasActive){\r
- this.onEnd(e);\r
- this.fireEvent('dragend', this, e);\r
- }\r
- },\r
-\r
- triggerStart: function(isTimer){\r
- this.clearStart();\r
- this.active = true;\r
- this.onStart(this.startXY);\r
- this.fireEvent('dragstart', this, this.startXY);\r
- },\r
-\r
- clearStart : function(){\r
- if(this.timer){\r
- clearTimeout(this.timer);\r
- delete this.timer;\r
- }\r
- },\r
-\r
- stopSelect : function(e){\r
- e.stopEvent();\r
- return false;\r
- },\r
-\r
- onBeforeStart : function(e){\r
-\r
- },\r
-\r
- onStart : function(xy){\r
-\r
- },\r
-\r
- onDrag : function(e){\r
-\r
- },\r
-\r
- onEnd : function(e){\r
-\r
- },\r
-\r
- getDragTarget : function(){\r
- return this.dragTarget;\r
- },\r
-\r
- getDragCt : function(){\r
- return this.el;\r
- },\r
-\r
- getXY : function(constrain){\r
- return constrain ?\r
- this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;\r
- },\r
-\r
- getOffset : function(constrain){\r
- var xy = this.getXY(constrain);\r
- var s = this.startXY;\r
- return [s[0]-xy[0], s[1]-xy[1]];\r
- },\r
-\r
- constrainModes: {\r
- 'point' : function(xy){\r
-\r
- if(!this.elRegion){\r
- this.elRegion = this.getDragCt().getRegion();\r
- }\r
-\r
- var dr = this.dragRegion;\r
-\r
- dr.left = xy[0];\r
- dr.top = xy[1];\r
- dr.right = xy[0];\r
- dr.bottom = xy[1];\r
-\r
- dr.constrainTo(this.elRegion);\r
-\r
- return [dr.left, dr.top];\r
- }\r
- }\r
-});</pre> \r
-</body>\r
-</html>
\ No newline at end of file
+<!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"><span id='Ext-dd-DragTracker'>/**
+</span> * @class Ext.dd.DragTracker
+ * A DragTracker listens for drag events on an Element and fires events at the start and end of the drag,
+ * as well as during the drag. This is useful for components such as {@link Ext.slider.Multi}, where there is
+ * an element that can be dragged around to change the Slider's value.
+ * DragTracker provides a series of template methods that should be overridden to provide functionality
+ * in response to detected drag operations. These are onBeforeStart, onStart, onDrag and onEnd.
+ * See {@link Ext.slider.Multi}'s initEvents function for an example implementation.
+ */
+Ext.define('Ext.dd.DragTracker', {
+
+ uses: ['Ext.util.Region'],
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+<span id='Ext-dd-DragTracker-property-active'> /**
+</span> * @property {Boolean} active
+ * Read-only property indicated whether the user is currently dragging this
+ * tracker.
+ */
+ active: false,
+
+<span id='Ext-dd-DragTracker-property-dragTarget'> /**
+</span> * @property {HTMLElement} dragTarget
+ * <p><b>Only valid during drag operations. Read-only.</b></p>
+ * <p>The element being dragged.</p>
+ * <p>If the {@link #delegate} option is used, this will be the delegate element which was mousedowned.</p>
+ */
+
+<span id='Ext-dd-DragTracker-cfg-trackOver'> /**
+</span> * @cfg {Boolean} trackOver
+ * <p>Defaults to <code>false</code>. Set to true to fire mouseover and mouseout events when the mouse enters or leaves the target element.</p>
+ * <p>This is implicitly set when an {@link #overCls} is specified.</p>
+ * <b>If the {@link #delegate} option is used, these events fire only when a delegate element is entered of left.</b>.
+ */
+ trackOver: false,
+
+<span id='Ext-dd-DragTracker-cfg-overCls'> /**
+</span> * @cfg {String} overCls
+ * <p>A CSS class to add to the DragTracker's target element when the element (or, if the {@link #delegate} option is used,
+ * when a delegate element) is mouseovered.</p>
+ * <b>If the {@link #delegate} option is used, these events fire only when a delegate element is entered of left.</b>.
+ */
+
+<span id='Ext-dd-DragTracker-cfg-constrainTo'> /**
+</span> * @cfg {Ext.util.Region/Ext.Element} constrainTo
+ * <p>A {@link Ext.util.Region Region} (Or an element from which a Region measurement will be read) which is used to constrain
+ * the result of the {@link #getOffset} call.</p>
+ * <p>This may be set any time during the DragTracker's lifecycle to set a dynamic constraining region.</p>
+ */
+
+<span id='Ext-dd-DragTracker-cfg-tolerance'> /**
+</span> * @cfg {Number} tolerance
+ * Number of pixels the drag target must be moved before dragging is
+ * considered to have started. Defaults to <code>5</code>.
+ */
+ tolerance: 5,
+
+<span id='Ext-dd-DragTracker-cfg-autoStart'> /**
+</span> * @cfg {Boolean/Number} autoStart
+ * Defaults to <code>false</code>. Specify <code>true</code> to defer trigger start by 1000 ms.
+ * Specify a Number for the number of milliseconds to defer trigger start.
+ */
+ autoStart: false,
+
+<span id='Ext-dd-DragTracker-cfg-delegate'> /**
+</span> * @cfg {String} delegate
+ * Optional. <p>A {@link Ext.DomQuery DomQuery} selector which identifies child elements within the DragTracker's encapsulating
+ * Element which are the tracked elements. This limits tracking to only begin when the matching elements are mousedowned.</p>
+ * <p>This may also be a specific child element within the DragTracker's encapsulating element to use as the tracked element.</p>
+ */
+
+<span id='Ext-dd-DragTracker-cfg-preventDefault'> /**
+</span> * @cfg {Boolean} preventDefault
+ * Specify <code>false</code> to enable default actions on onMouseDown events. Defaults to <code>true</code>.
+ */
+
+<span id='Ext-dd-DragTracker-cfg-stopEvent'> /**
+</span> * @cfg {Boolean} stopEvent
+ * Specify <code>true</code> to stop the <code>mousedown</code> event from bubbling to outer listeners from the target element (or its delegates). Defaults to <code>false</code>.
+ */
+
+ constructor : function(config){
+ Ext.apply(this, config);
+ this.addEvents(
+<span id='Ext-dd-DragTracker-event-mouseover'> /**
+</span> * @event mouseover <p><b>Only available when {@link #trackOver} is <code>true</code></b></p>
+ * <p>Fires when the mouse enters the DragTracker's target element (or if {@link #delegate} is
+ * used, when the mouse enters a delegate element).</p>
+ * @param {Object} this
+ * @param {Object} e event object
+ * @param {HTMLElement} target The element mouseovered.
+ */
+ 'mouseover',
+
+<span id='Ext-dd-DragTracker-event-mouseout'> /**
+</span> * @event mouseout <p><b>Only available when {@link #trackOver} is <code>true</code></b></p>
+ * <p>Fires when the mouse exits the DragTracker's target element (or if {@link #delegate} is
+ * used, when the mouse exits a delegate element).</p>
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mouseout',
+
+<span id='Ext-dd-DragTracker-event-mousedown'> /**
+</span> * @event mousedown <p>Fires when the mouse button is pressed down, but before a drag operation begins. The
+ * drag operation begins after either the mouse has been moved by {@link #tolerance} pixels, or after
+ * the {@link #autoStart} timer fires.</p>
+ * <p>Return false to veto the drag operation.</p>
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mousedown',
+
+<span id='Ext-dd-DragTracker-event-mouseup'> /**
+</span> * @event mouseup
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mouseup',
+
+<span id='Ext-dd-DragTracker-event-mousemove'> /**
+</span> * @event mousemove Fired when the mouse is moved. Returning false cancels the drag operation.
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mousemove',
+
+<span id='Ext-dd-DragTracker-event-beforestart'> /**
+</span> * @event beforestart
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'beforedragstart',
+
+<span id='Ext-dd-DragTracker-event-dragstart'> /**
+</span> * @event dragstart
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'dragstart',
+
+<span id='Ext-dd-DragTracker-event-dragend'> /**
+</span> * @event dragend
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'dragend',
+
+<span id='Ext-dd-DragTracker-event-drag'> /**
+</span> * @event drag
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'drag'
+ );
+
+ this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
+
+ if (this.el) {
+ this.initEl(this.el);
+ }
+
+ // Dont pass the config so that it is not applied to 'this' again
+ this.mixins.observable.constructor.call(this);
+ if (this.disabled) {
+ this.disable();
+ }
+
+ },
+
+<span id='Ext-dd-DragTracker-method-initEl'> /**
+</span> * Initializes the DragTracker on a given element.
+ * @param {Ext.Element/HTMLElement} el The element
+ */
+ initEl: function(el) {
+ this.el = Ext.get(el);
+
+ // The delegate option may also be an element on which to listen
+ this.handle = Ext.get(this.delegate);
+
+ // If delegate specified an actual element to listen on, we do not use the delegate listener option
+ this.delegate = this.handle ? undefined : this.delegate;
+
+ if (!this.handle) {
+ this.handle = this.el;
+ }
+
+ // Add a mousedown listener which reacts only on the elements targeted by the delegate config.
+ // We process mousedown to begin tracking.
+ this.mon(this.handle, {
+ mousedown: this.onMouseDown,
+ delegate: this.delegate,
+ scope: this
+ });
+
+ // If configured to do so, track mouse entry and exit into the target (or delegate).
+ // The mouseover and mouseout CANNOT be replaced with mouseenter and mouseleave
+ // because delegate cannot work with those pseudoevents. Entry/exit checking is done in the handler.
+ if (this.trackOver || this.overCls) {
+ this.mon(this.handle, {
+ mouseover: this.onMouseOver,
+ mouseout: this.onMouseOut,
+ delegate: this.delegate,
+ scope: this
+ });
+ }
+ },
+
+ disable: function() {
+ this.disabled = true;
+ },
+
+ enable: function() {
+ this.disabled = false;
+ },
+
+ destroy : function() {
+ this.clearListeners();
+ delete this.el;
+ },
+
+ // When the pointer enters a tracking element, fire a mouseover if the mouse entered from outside.
+ // This is mouseenter functionality, but we cannot use mouseenter because we are using "delegate" to filter mouse targets
+ onMouseOver: function(e, target) {
+ var me = this;
+ if (!me.disabled) {
+ if (Ext.EventManager.contains(e) || me.delegate) {
+ me.mouseIsOut = false;
+ if (me.overCls) {
+ me.el.addCls(me.overCls);
+ }
+ me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
+ }
+ }
+ },
+
+ // When the pointer exits a tracking element, fire a mouseout.
+ // This is mouseleave functionality, but we cannot use mouseleave because we are using "delegate" to filter mouse targets
+ onMouseOut: function(e) {
+ if (this.mouseIsDown) {
+ this.mouseIsOut = true;
+ } else {
+ if (this.overCls) {
+ this.el.removeCls(this.overCls);
+ }
+ this.fireEvent('mouseout', this, e);
+ }
+ },
+
+ onMouseDown: function(e, target){
+ // If this is disabled, or the mousedown has been processed by an upstream DragTracker, return
+ if (this.disabled ||e.dragTracked) {
+ return;
+ }
+
+ // This information should be available in mousedown listener and onBeforeStart implementations
+ this.dragTarget = this.delegate ? target : this.handle.dom;
+ this.startXY = this.lastXY = e.getXY();
+ this.startRegion = Ext.fly(this.dragTarget).getRegion();
+
+ if (this.fireEvent('mousedown', this, e) === false ||
+ this.fireEvent('beforedragstart', this, e) === false ||
+ this.onBeforeStart(e) === false) {
+ return;
+ }
+
+ // Track when the mouse is down so that mouseouts while the mouse is down are not processed.
+ // The onMouseOut method will only ever be called after mouseup.
+ this.mouseIsDown = true;
+
+ // Flag for downstream DragTracker instances that the mouse is being tracked.
+ e.dragTracked = true;
+
+ if (this.preventDefault !== false) {
+ e.preventDefault();
+ }
+ Ext.getDoc().on({
+ scope: this,
+ mouseup: this.onMouseUp,
+ mousemove: this.onMouseMove,
+ selectstart: this.stopSelect
+ });
+ if (this.autoStart) {
+ this.timer = Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
+ }
+ },
+
+ onMouseMove: function(e, target){
+ // BrowserBug: IE hack to see if button was released outside of window.
+ // Needed in IE6-9 in quirks and strictmode
+ if (this.active && Ext.isIE && !e.browserEvent.button) {
+ e.preventDefault();
+ this.onMouseUp(e);
+ return;
+ }
+
+ e.preventDefault();
+ var xy = e.getXY(),
+ s = this.startXY;
+
+ this.lastXY = xy;
+ if (!this.active) {
+ if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
+ this.triggerStart(e);
+ } else {
+ return;
+ }
+ }
+
+ // Returning false from a mousemove listener deactivates
+ if (this.fireEvent('mousemove', this, e) === false) {
+ this.onMouseUp(e);
+ } else {
+ this.onDrag(e);
+ this.fireEvent('drag', this, e);
+ }
+ },
+
+ onMouseUp: function(e) {
+ // Clear the flag which ensures onMouseOut fires only after the mouse button
+ // is lifted if the mouseout happens *during* a drag.
+ this.mouseIsDown = false;
+
+ // If we mouseouted the el *during* the drag, the onMouseOut method will not have fired. Ensure that it gets processed.
+ if (this.mouseIsOut) {
+ this.mouseIsOut = false;
+ this.onMouseOut(e);
+ }
+ e.preventDefault();
+ this.fireEvent('mouseup', this, e);
+ this.endDrag(e);
+ },
+
+<span id='Ext-dd-DragTracker-method-endDrag'> /**
+</span> * @private
+ * Stop the drag operation, and remove active mouse listeners.
+ */
+ endDrag: function(e) {
+ var doc = Ext.getDoc(),
+ wasActive = this.active;
+
+ doc.un('mousemove', this.onMouseMove, this);
+ doc.un('mouseup', this.onMouseUp, this);
+ doc.un('selectstart', this.stopSelect, this);
+ this.clearStart();
+ this.active = false;
+ if (wasActive) {
+ this.onEnd(e);
+ this.fireEvent('dragend', this, e);
+ }
+ // Private property calculated when first required and only cached during a drag
+ delete this._constrainRegion;
+
+ // Remove flag from event singleton. Using "Ext.EventObject" here since "endDrag" is called directly in some cases without an "e" param
+ delete Ext.EventObject.dragTracked;
+ },
+
+ triggerStart: function(e) {
+ this.clearStart();
+ this.active = true;
+ this.onStart(e);
+ this.fireEvent('dragstart', this, e);
+ },
+
+ clearStart : function() {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ delete this.timer;
+ }
+ },
+
+ stopSelect : function(e) {
+ e.stopEvent();
+ return false;
+ },
+
+<span id='Ext-dd-DragTracker-method-onBeforeStart'> /**
+</span> * Template method which should be overridden by each DragTracker instance. Called when the user first clicks and
+ * holds the mouse button down. Return false to disallow the drag
+ * @param {Ext.EventObject} e The event object
+ * @template
+ */
+ onBeforeStart : function(e) {
+
+ },
+
+<span id='Ext-dd-DragTracker-method-onStart'> /**
+</span> * Template method which should be overridden by each DragTracker instance. Called when a drag operation starts
+ * (e.g. the user has moved the tracked element beyond the specified tolerance)
+ * @param {Ext.EventObject} e The event object
+ * @template
+ */
+ onStart : function(xy) {
+
+ },
+
+<span id='Ext-dd-DragTracker-method-onDrag'> /**
+</span> * Template method which should be overridden by each DragTracker instance. Called whenever a drag has been detected.
+ * @param {Ext.EventObject} e The event object
+ * @template
+ */
+ onDrag : function(e) {
+
+ },
+
+<span id='Ext-dd-DragTracker-method-onEnd'> /**
+</span> * Template method which should be overridden by each DragTracker instance. Called when a drag operation has been completed
+ * (e.g. the user clicked and held the mouse down, dragged the element and then released the mouse button)
+ * @param {Ext.EventObject} e The event object
+ * @template
+ */
+ onEnd : function(e) {
+
+ },
+
+<span id='Ext-dd-DragTracker-method-getDragTarget'> /**
+</span> * </p>Returns the drag target. This is usually the DragTracker's encapsulating element.</p>
+ * <p>If the {@link #delegate} option is being used, this may be a child element which matches the
+ * {@link #delegate} selector.</p>
+ * @return {Ext.Element} The element currently being tracked.
+ */
+ getDragTarget : function(){
+ return this.dragTarget;
+ },
+
+<span id='Ext-dd-DragTracker-method-getDragCt'> /**
+</span> * @private
+ * @returns {Ext.Element} The DragTracker's encapsulating element.
+ */
+ getDragCt : function(){
+ return this.el;
+ },
+
+<span id='Ext-dd-DragTracker-method-getConstrainRegion'> /**
+</span> * @private
+ * Return the Region into which the drag operation is constrained.
+ * Either the XY pointer itself can be constrained, or the dragTarget element
+ * The private property _constrainRegion is cached until onMouseUp
+ */
+ getConstrainRegion: function() {
+ if (this.constrainTo) {
+ if (this.constrainTo instanceof Ext.util.Region) {
+ return this.constrainTo;
+ }
+ if (!this._constrainRegion) {
+ this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
+ }
+ } else {
+ if (!this._constrainRegion) {
+ this._constrainRegion = this.getDragCt().getViewRegion();
+ }
+ }
+ return this._constrainRegion;
+ },
+
+ getXY : function(constrain){
+ return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY;
+ },
+
+<span id='Ext-dd-DragTracker-method-getOffset'> /**
+</span> * Returns the X, Y offset of the current mouse position from the mousedown point.
+ *
+ * This method may optionally constrain the real offset values, and returns a point coerced in one
+ * of two modes:
+ *
+ * - `point`
+ * The current mouse position is coerced into the constrainRegion and the resulting position is returned.
+ * - `dragTarget`
+ * The new {@link Ext.util.Region Region} of the {@link #getDragTarget dragTarget} is calculated
+ * based upon the current mouse position, and then coerced into the constrainRegion. The returned
+ * mouse position is then adjusted by the same delta as was used to coerce the region.\
+ *
+ * @param constrainMode {String} (Optional) If omitted the true mouse position is returned. May be passed
+ * as `point` or `dragTarget`. See above.
+ * @returns {Number[]} The `X, Y` offset from the mousedown point, optionally constrained.
+ */
+ getOffset : function(constrain){
+ var xy = this.getXY(constrain),
+ s = this.startXY;
+
+ return [xy[0]-s[0], xy[1]-s[1]];
+ },
+
+ constrainModes: {
+ // Constrain the passed point to within the constrain region
+ point: function(me, xy) {
+ var dr = me.dragRegion,
+ constrainTo = me.getConstrainRegion();
+
+ // No constraint
+ if (!constrainTo) {
+ return xy;
+ }
+
+ dr.x = dr.left = dr[0] = dr.right = xy[0];
+ dr.y = dr.top = dr[1] = dr.bottom = xy[1];
+ dr.constrainTo(constrainTo);
+
+ return [dr.left, dr.top];
+ },
+
+ // Constrain the dragTarget to within the constrain region. Return the passed xy adjusted by the same delta.
+ dragTarget: function(me, xy) {
+ var s = me.startXY,
+ dr = me.startRegion.copy(),
+ constrainTo = me.getConstrainRegion(),
+ adjust;
+
+ // No constraint
+ if (!constrainTo) {
+ return xy;
+ }
+
+ // See where the passed XY would put the dragTarget if translated by the unconstrained offset.
+ // If it overflows, we constrain the passed XY to bring the potential
+ // region back within the boundary.
+ dr.translateBy(xy[0]-s[0], xy[1]-s[1]);
+
+ // Constrain the X coordinate by however much the dragTarget overflows
+ if (dr.right > constrainTo.right) {
+ xy[0] += adjust = (constrainTo.right - dr.right); // overflowed the right
+ dr.left += adjust;
+ }
+ if (dr.left < constrainTo.left) {
+ xy[0] += (constrainTo.left - dr.left); // overflowed the left
+ }
+
+ // Constrain the Y coordinate by however much the dragTarget overflows
+ if (dr.bottom > constrainTo.bottom) {
+ xy[1] += adjust = (constrainTo.bottom - dr.bottom); // overflowed the bottom
+ dr.top += adjust;
+ }
+ if (dr.top < constrainTo.top) {
+ xy[1] += (constrainTo.top - dr.top); // overflowed the top
+ }
+ return xy;
+ }
+ }
+});</pre>
+</body>
+</html>