/** * @class Ext.slider.Thumb * @private * Represents a single thumb element on a Slider. This would not usually be created manually and would instead * be created internally by an {@link Ext.slider.Multi Multi slider}. */ Ext.define('Ext.slider.Thumb', { requires: ['Ext.dd.DragTracker', 'Ext.util.Format'], /** * @private * @property {Number} topThumbZIndex * The number used internally to set the z index of the top thumb (see promoteThumb for details) */ topZIndex: 10000, /** * @cfg {Ext.slider.MultiSlider} slider (required) * The Slider to render to. */ /** * Creates new slider thumb. * @param {Object} [config] Config object. */ constructor: function(config) { var me = this; /** * @property {Ext.slider.MultiSlider} slider * The slider this thumb is contained within */ Ext.apply(me, config || {}, { cls: Ext.baseCSSPrefix + 'slider-thumb', /** * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings */ constrain: false }); me.callParent([config]); }, /** * Renders the thumb into a slider */ render: function() { var me = this; me.el = me.slider.innerEl.insertFirst(me.getElConfig()); me.onRender(); }, onRender: function() { if (this.disabled) { this.disable(); } this.initEvents(); }, getElConfig: function() { var me = this, slider = me.slider, style = {}; style[slider.vertical ? 'bottom' : 'left'] = slider.calculateThumbPosition(slider.normalizeValue(me.value)) + '%'; return { style: style, id : this.id, cls : this.cls }; }, /** * @private * move the thumb */ move: function(v, animate) { var el = this.el, styleProp = this.slider.vertical ? 'bottom' : 'left', to, from; v += '%'; if (!animate) { el.dom.style[styleProp] = v; } else { to = {}; to[styleProp] = v; if (!Ext.supports.GetPositionPercentage) { from = {}; from[styleProp] = el.dom.style[styleProp]; } new Ext.fx.Anim({ target: el, duration: 350, from: from, to: to }); } }, /** * @private * Bring thumb dom element to front. */ bringToFront: function() { this.el.setStyle('zIndex', this.topZIndex); }, /** * @private * Send thumb dom element to back. */ sendToBack: function() { this.el.setStyle('zIndex', ''); }, /** * Enables the thumb if it is currently disabled */ enable: function() { var me = this; me.disabled = false; if (me.el) { me.el.removeCls(me.slider.disabledCls); } }, /** * Disables the thumb if it is currently enabled */ disable: function() { var me = this; me.disabled = true; if (me.el) { me.el.addCls(me.slider.disabledCls); } }, /** * Sets up an Ext.dd.DragTracker for this thumb */ initEvents: function() { var me = this, el = me.el; me.tracker = new Ext.dd.DragTracker({ onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me), onStart : Ext.Function.bind(me.onDragStart, me), onDrag : Ext.Function.bind(me.onDrag, me), onEnd : Ext.Function.bind(me.onDragEnd, me), tolerance : 3, autoStart : 300, overCls : Ext.baseCSSPrefix + 'slider-thumb-over' }); me.tracker.initEl(el); }, /** * @private * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled, * this returns false to disable the DragTracker too. * @return {Boolean} False if the slider is currently disabled */ onBeforeDragStart : function(e) { if (this.disabled) { return false; } else { this.slider.promoteThumb(this); return true; } }, /** * @private * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class * to the thumb and fires the 'dragstart' event */ onDragStart: function(e){ var me = this; me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag'); me.dragging = me.slider.dragging = true; me.dragStartValue = me.value; me.slider.fireEvent('dragstart', me.slider, e, me); }, /** * @private * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag */ onDrag: function(e) { var me = this, slider = me.slider, index = me.index, newValue = me.getValueFromTracker(), above, below; // If dragged out of range, value will be undefined if (newValue !== undefined) { if (me.constrain) { above = slider.thumbs[index + 1]; below = slider.thumbs[index - 1]; if (below !== undefined && newValue <= below.value) { newValue = below.value; } if (above !== undefined && newValue >= above.value) { newValue = above.value; } } slider.setValue(index, newValue, false); slider.fireEvent('drag', slider, e, me); } }, getValueFromTracker: function() { var slider = this.slider, trackPoint = slider.getTrackpoint(this.tracker.getXY()); // If dragged out of range, value will be undefined if (trackPoint !== undefined) { return slider.reversePixelValue(trackPoint); } }, /** * @private * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and * fires the 'changecomplete' event with the new value */ onDragEnd: function(e) { var me = this, slider = me.slider, value = me.value; me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag'); me.dragging = slider.dragging = false; slider.fireEvent('dragend', slider, e); if (me.dragStartValue != value) { slider.fireEvent('changecomplete', slider, value, me); } }, destroy: function() { Ext.destroy(this.tracker); } });