Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / slider / Thumb.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.slider.Thumb
17  * @extends Ext.Base
18  * @private
19  * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
20  * be created internally by an {@link Ext.slider.Multi Ext.Slider}.
21  */
22 Ext.define('Ext.slider.Thumb', {
23     requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
24     /**
25      * @private
26      * @property topThumbZIndex
27      * @type Number
28      * The number used internally to set the z index of the top thumb (see promoteThumb for details)
29      */
30     topZIndex: 10000,
31     /**
32      * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
33      */
34     /**
35      * Creates new slider thumb.
36      * @param {Object} config (optional) Config object.
37      */
38     constructor: function(config) {
39         var me = this;
40         
41         /**
42          * @property slider
43          * @type Ext.slider.MultiSlider
44          * The slider this thumb is contained within
45          */
46         Ext.apply(me, config || {}, {
47             cls: Ext.baseCSSPrefix + 'slider-thumb',
48
49             /**
50              * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
51              */
52             constrain: false
53         });
54         me.callParent([config]);
55
56         if (me.slider.vertical) {
57             Ext.apply(me, Ext.slider.Thumb.Vertical);
58         }
59     },
60
61     /**
62      * Renders the thumb into a slider
63      */
64     render: function() {
65         var me = this;
66         
67         me.el = me.slider.innerEl.insertFirst({cls: me.cls});
68         if (me.disabled) {
69             me.disable();
70         }
71         me.initEvents();
72     },
73     
74     /**
75      * @private
76      * move the thumb
77      */
78     move: function(v, animate){
79         if(!animate){
80             this.el.setLeft(v);
81         }else{
82             Ext.create('Ext.fx.Anim', {
83                 target: this.el,
84                 duration: 350,
85                 to: {
86                     left: v
87                 }
88             });
89         }
90     },
91
92     /**
93      * @private
94      * Bring thumb dom element to front.
95      */
96     bringToFront: function() {
97         this.el.setStyle('zIndex', this.topZIndex);
98     },
99     
100     /**
101      * @private
102      * Send thumb dom element to back.
103      */
104     sendToBack: function() {
105         this.el.setStyle('zIndex', '');
106     },
107     
108     /**
109      * Enables the thumb if it is currently disabled
110      */
111     enable: function() {
112         var me = this;
113         
114         me.disabled = false;
115         if (me.el) {
116             me.el.removeCls(me.slider.disabledCls);
117         }
118     },
119
120     /**
121      * Disables the thumb if it is currently enabled
122      */
123     disable: function() {
124         var me = this;
125         
126         me.disabled = true;
127         if (me.el) {
128             me.el.addCls(me.slider.disabledCls);
129         }
130     },
131
132     /**
133      * Sets up an Ext.dd.DragTracker for this thumb
134      */
135     initEvents: function() {
136         var me = this,
137             el = me.el;
138
139         me.tracker = Ext.create('Ext.dd.DragTracker', {
140             onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me),
141             onStart      : Ext.Function.bind(me.onDragStart, me),
142             onDrag       : Ext.Function.bind(me.onDrag, me),
143             onEnd        : Ext.Function.bind(me.onDragEnd, me),
144             tolerance    : 3,
145             autoStart    : 300,
146             overCls      : Ext.baseCSSPrefix + 'slider-thumb-over'
147         });
148
149         me.tracker.initEl(el);
150     },
151
152     /**
153      * @private
154      * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
155      * this returns false to disable the DragTracker too.
156      * @return {Boolean} False if the slider is currently disabled
157      */
158     onBeforeDragStart : function(e) {
159         if (this.disabled) {
160             return false;
161         } else {
162             this.slider.promoteThumb(this);
163             return true;
164         }
165     },
166
167     /**
168      * @private
169      * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
170      * to the thumb and fires the 'dragstart' event
171      */
172     onDragStart: function(e){
173         var me = this;
174         
175         me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
176         me.dragging = true;
177         me.dragStartValue = me.value;
178
179         me.slider.fireEvent('dragstart', me.slider, e, me);
180     },
181
182     /**
183      * @private
184      * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
185      * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
186      */
187     onDrag: function(e) {
188         var me       = this,
189             slider   = me.slider,
190             index    = me.index,
191             newValue = me.getNewValue(),
192             above,
193             below;
194
195         if (me.constrain) {
196             above = slider.thumbs[index + 1];
197             below = slider.thumbs[index - 1];
198
199             if (below !== undefined && newValue <= below.value) {
200                 newValue = below.value;
201             }
202             
203             if (above !== undefined && newValue >= above.value) {
204                 newValue = above.value;
205             }
206         }
207
208         slider.setValue(index, newValue, false);
209         slider.fireEvent('drag', slider, e, me);
210     },
211
212     getNewValue: function() {
213         var slider = this.slider,
214             pos = slider.innerEl.translatePoints(this.tracker.getXY());
215
216         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
217     },
218
219     /**
220      * @private
221      * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
222      * fires the 'changecomplete' event with the new value
223      */
224     onDragEnd: function(e) {
225         var me     = this,
226             slider = me.slider,
227             value  = me.value;
228
229         me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
230
231         me.dragging = false;
232         slider.fireEvent('dragend', slider, e);
233
234         if (me.dragStartValue != value) {
235             slider.fireEvent('changecomplete', slider, value, me);
236         }
237     },
238
239     destroy: function() {
240         Ext.destroy(this.tracker);
241     },
242     statics: {
243         // Method overrides to support vertical dragging of thumb within slider
244         Vertical: {
245             getNewValue: function() {
246                 var slider   = this.slider,
247                     innerEl  = slider.innerEl,
248                     pos      = innerEl.translatePoints(this.tracker.getXY()),
249                     bottom   = innerEl.getHeight() - pos.top;
250
251                 return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
252             },
253             move: function(v, animate) {
254                 if (!animate) {
255                     this.el.setBottom(v);
256                 } else {
257                     Ext.create('Ext.fx.Anim', {
258                         target: this.el,
259                         duration: 350,
260                         to: {
261                             bottom: v
262                         }
263                     });
264                 }
265             }
266         }
267     }
268 });
269