-/**\r
- * @class Ext.dd.DragTracker\r
- * @extends Ext.util.Observable\r
- */\r
-Ext.dd.DragTracker = Ext.extend(Ext.util.Observable, {\r
- /**\r
- * @cfg {Boolean} active\r
- * Defaults to <tt>false</tt>.\r
- */ \r
- active: false,\r
- /**\r
- * @cfg {Number} tolerance\r
- * Defaults to <tt>5</tt>.\r
- */ \r
- tolerance: 5,\r
- /**\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
- /**\r
- * @event mousedown\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mousedown',\r
- /**\r
- * @event mouseup\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mouseup',\r
- /**\r
- * @event mousemove\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'mousemove',\r
- /**\r
- * @event dragstart\r
- * @param {Object} this\r
- * @param {Object} startXY the page coordinates of the event\r
- */\r
- 'dragstart',\r
- /**\r
- * @event dragend\r
- * @param {Object} this\r
- * @param {Object} e event object\r
- */\r
- 'dragend',\r
- /**\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
+/**
+ * @class Ext.dd.DragTracker
+ * @extends Ext.util.Observable
+ * 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.MultiSlider}, 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.MultiSlider}'s initEvents function for an example implementation.
+ */
+Ext.dd.DragTracker = Ext.extend(Ext.util.Observable, {
+ /**
+ * @cfg {Boolean} active
+ * Defaults to <tt>false</tt>.
+ */
+ active: false,
+ /**
+ * @cfg {Number} tolerance
+ * Number of pixels the drag target must be moved before dragging is considered to have started. Defaults to <tt>5</tt>.
+ */
+ tolerance: 5,
+ /**
+ * @cfg {Boolean/Number} autoStart
+ * Defaults to <tt>false</tt>. Specify <tt>true</tt> to defer trigger start by 1000 ms.
+ * Specify a Number for the number of milliseconds to defer trigger start.
+ */
+ autoStart: false,
+
+ constructor : function(config){
+ Ext.apply(this, config);
+ this.addEvents(
+ /**
+ * @event mousedown
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mousedown',
+ /**
+ * @event mouseup
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mouseup',
+ /**
+ * @event mousemove
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'mousemove',
+ /**
+ * @event dragstart
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'dragstart',
+ /**
+ * @event dragend
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'dragend',
+ /**
+ * @event drag
+ * @param {Object} this
+ * @param {Object} e event object
+ */
+ 'drag'
+ );
+
+ this.dragRegion = new Ext.lib.Region(0,0,0,0);
+
+ if(this.el){
+ this.initEl(this.el);
+ }
+ Ext.dd.DragTracker.superclass.constructor.call(this, config);
+ },
+
+ initEl: function(el){
+ this.el = Ext.get(el);
+ el.on('mousedown', this.onMouseDown, this,
+ this.delegate ? {delegate: this.delegate} : undefined);
+ },
+
+ destroy : function(){
+ this.el.un('mousedown', this.onMouseDown, this);
+ delete this.el;
+ },
+
+ onMouseDown: function(e, target){
+ if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
+ this.startXY = this.lastXY = e.getXY();
+ this.dragTarget = this.delegate ? target : this.el.dom;
+ 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 = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [e]);
+ }
+ }
+ },
+
+ onMouseMove: function(e, target){
+ // HACK: IE hack to see if button was released outside of window. */
+ 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.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
+ this.triggerStart(e);
+ }else{
+ return;
+ }
+ }
+ this.fireEvent('mousemove', this, e);
+ this.onDrag(e);
+ this.fireEvent('drag', this, e);
+ },
+
+ onMouseUp: 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);
+ e.preventDefault();
+ this.clearStart();
+ this.active = false;
+ delete this.elRegion;
+ this.fireEvent('mouseup', this, e);
+ if(wasActive){
+ this.onEnd(e);
+ this.fireEvent('dragend', this, e);
+ }
+ },
+
+ 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;
+ },
+
+ /**
+ * 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
+ */
+ onBeforeStart : function(e) {
+
+ },
+
+ /**
+ * 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
+ */
+ onStart : function(xy) {
+
+ },
+
+ /**
+ * Template method which should be overridden by each DragTracker instance. Called whenever a drag has been detected.
+ * @param {Ext.EventObject} e The event object
+ */
+ onDrag : function(e) {
+
+ },
+
+ /**
+ * 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
+ */
+ onEnd : function(e) {
+
+ },
+
+ /**
+ * Returns the drag target
+ * @return {Ext.Element} The element currently being tracked
+ */
+ getDragTarget : function(){
+ return this.dragTarget;
+ },
+
+ getDragCt : function(){
+ return this.el;
+ },
+
+ getXY : function(constrain){
+ return constrain ?
+ this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
+ },
+
+ getOffset : function(constrain){
+ var xy = this.getXY(constrain),
+ s = this.startXY;
+ return [s[0]-xy[0], s[1]-xy[1]];
+ },
+
+ constrainModes: {
+ 'point' : function(xy){
+
+ if(!this.elRegion){
+ this.elRegion = this.getDragCt().getRegion();
+ }
+
+ var dr = this.dragRegion;
+
+ dr.left = xy[0];
+ dr.top = xy[1];
+ dr.right = xy[0];
+ dr.bottom = xy[1];
+
+ dr.constrainTo(this.elRegion);
+
+ return [dr.left, dr.top];
+ }
+ }