/** * @class Ext.ux.Spinner * @extends Ext.util.Observable * Creates a Spinner control utilized by Ext.ux.form.SpinnerField */ Ext.ux.Spinner = Ext.extend(Ext.util.Observable, { incrementValue: 1, alternateIncrementValue: 5, triggerClass: 'x-form-spinner-trigger', splitterClass: 'x-form-spinner-splitter', alternateKey: Ext.EventObject.shiftKey, defaultValue: 0, accelerate: false, constructor: function(config){ Ext.ux.Spinner.superclass.constructor.call(this, config); Ext.apply(this, config); this.mimicing = false; }, init: function(field){ this.field = field; field.afterMethod('onRender', this.doRender, this); field.afterMethod('onEnable', this.doEnable, this); field.afterMethod('onDisable', this.doDisable, this); field.afterMethod('afterRender', this.doAfterRender, this); field.afterMethod('onResize', this.doResize, this); field.afterMethod('onFocus', this.doFocus, this); field.beforeMethod('onDestroy', this.doDestroy, this); }, doRender: function(ct, position){ var el = this.el = this.field.getEl(); var f = this.field; if (!f.wrap) { f.wrap = this.wrap = el.wrap({ cls: "x-form-field-wrap" }); } else { this.wrap = f.wrap.addClass('x-form-field-wrap'); } this.trigger = this.wrap.createChild({ tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass }); if (!f.width) { this.wrap.setWidth(el.getWidth() + this.trigger.getWidth()); } this.splitter = this.wrap.createChild({ tag: 'div', cls: this.splitterClass, style: 'width:13px; height:2px;' }); this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show(); this.proxy = this.trigger.createProxy('', this.splitter, true); this.proxy.addClass("x-form-spinner-proxy"); this.proxy.setStyle('left', '0px'); this.proxy.setSize(14, 1); this.proxy.hide(); this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", { dragElId: this.proxy.id }); this.initTrigger(); this.initSpinner(); }, doAfterRender: function(){ var y; if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) { this.el.position(); this.el.setY(y); } }, doEnable: function(){ if (this.wrap) { this.wrap.removeClass(this.field.disabledClass); } }, doDisable: function(){ if (this.wrap) { this.wrap.addClass(this.field.disabledClass); this.el.removeClass(this.field.disabledClass); } }, doResize: function(w, h){ if (typeof w == 'number') { this.el.setWidth(w - this.trigger.getWidth()); } this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth()); }, doFocus: function(){ if (!this.mimicing) { this.wrap.addClass('x-trigger-wrap-focus'); this.mimicing = true; Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, { delay: 10 }); this.el.on('keydown', this.checkTab, this); } }, // private checkTab: function(e){ if (e.getKey() == e.TAB) { this.triggerBlur(); } }, // private mimicBlur: function(e){ if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) { this.triggerBlur(); } }, // private triggerBlur: function(){ this.mimicing = false; Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this); this.el.un("keydown", this.checkTab, this); this.field.beforeBlur(); this.wrap.removeClass('x-trigger-wrap-focus'); this.field.onBlur.call(this.field); }, initTrigger: function(){ this.trigger.addClassOnOver('x-form-trigger-over'); this.trigger.addClassOnClick('x-form-trigger-click'); }, initSpinner: function(){ this.field.addEvents({ 'spin': true, 'spinup': true, 'spindown': true }); this.keyNav = new Ext.KeyNav(this.el, { "up": function(e){ e.preventDefault(); this.onSpinUp(); }, "down": function(e){ e.preventDefault(); this.onSpinDown(); }, "pageUp": function(e){ e.preventDefault(); this.onSpinUpAlternate(); }, "pageDown": function(e){ e.preventDefault(); this.onSpinDownAlternate(); }, scope: this }); this.repeater = new Ext.util.ClickRepeater(this.trigger, { accelerate: this.accelerate }); this.field.mon(this.repeater, "click", this.onTriggerClick, this, { preventDefault: true }); this.field.mon(this.trigger, { mouseover: this.onMouseOver, mouseout: this.onMouseOut, mousemove: this.onMouseMove, mousedown: this.onMouseDown, mouseup: this.onMouseUp, scope: this, preventDefault: true }); this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this); this.dd.setXConstraint(0, 0, 10) this.dd.setYConstraint(1500, 1500, 10); this.dd.endDrag = this.endDrag.createDelegate(this); this.dd.startDrag = this.startDrag.createDelegate(this); this.dd.onDrag = this.onDrag.createDelegate(this); }, onMouseOver: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown'; this.trigger.addClass(this.tmpHoverClass); }, //private onMouseOut: function(){ this.trigger.removeClass(this.tmpHoverClass); }, //private onMouseMove: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") || ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) { } }, //private onMouseDown: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown'; this.trigger.addClass(this.tmpClickClass); }, //private onMouseUp: function(){ this.trigger.removeClass(this.tmpClickClass); }, //private onTriggerClick: function(){ if (this.disabled || this.el.dom.readOnly) { return; } var middle = this.getMiddle(); var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down'; this['onSpin' + ud](); }, //private getMiddle: function(){ var t = this.trigger.getTop(); var h = this.trigger.getHeight(); var middle = t + (h / 2); return middle; }, //private //checks if control is allowed to spin isSpinnable: function(){ if (this.disabled || this.el.dom.readOnly) { Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly return false; } return true; }, handleMouseWheel: function(e){ //disable scrolling when not focused if (this.wrap.hasClass('x-trigger-wrap-focus') == false) { return; } var delta = e.getWheelDelta(); if (delta > 0) { this.onSpinUp(); e.stopEvent(); } else if (delta < 0) { this.onSpinDown(); e.stopEvent(); } }, //private startDrag: function(){ this.proxy.show(); this._previousY = Ext.fly(this.dd.getDragEl()).getTop(); }, //private endDrag: function(){ this.proxy.hide(); }, //private onDrag: function(){ if (this.disabled) { return; } var y = Ext.fly(this.dd.getDragEl()).getTop(); var ud = ''; if (this._previousY > y) { ud = 'Up'; } //up if (this._previousY < y) { ud = 'Down'; } //down if (ud != '') { this['onSpin' + ud](); } this._previousY = y; }, //private onSpinUp: function(){ if (this.isSpinnable() == false) { return; } if (Ext.EventObject.shiftKey == true) { this.onSpinUpAlternate(); return; } else { this.spin(false, false); } this.field.fireEvent("spin", this); this.field.fireEvent("spinup", this); }, //private onSpinDown: function(){ if (this.isSpinnable() == false) { return; } if (Ext.EventObject.shiftKey == true) { this.onSpinDownAlternate(); return; } else { this.spin(true, false); } this.field.fireEvent("spin", this); this.field.fireEvent("spindown", this); }, //private onSpinUpAlternate: function(){ if (this.isSpinnable() == false) { return; } this.spin(false, true); this.field.fireEvent("spin", this); this.field.fireEvent("spinup", this); }, //private onSpinDownAlternate: function(){ if (this.isSpinnable() == false) { return; } this.spin(true, true); this.field.fireEvent("spin", this); this.field.fireEvent("spindown", this); }, spin: function(down, alternate){ var v = parseFloat(this.field.getValue()); var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue; (down == true) ? v -= incr : v += incr; v = (isNaN(v)) ? this.defaultValue : v; v = this.fixBoundries(v); this.field.setRawValue(v); }, fixBoundries: function(value){ var v = value; if (this.field.minValue != undefined && v < this.field.minValue) { v = this.field.minValue; } if (this.field.maxValue != undefined && v > this.field.maxValue) { v = this.field.maxValue; } return this.fixPrecision(v); }, // private fixPrecision: function(value){ var nan = isNaN(value); if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) { return nan ? '' : value; } return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision)); }, doDestroy: function(){ if (this.trigger) { this.trigger.remove(); } if (this.wrap) { this.wrap.remove(); delete this.field.wrap; } if (this.splitter) { this.splitter.remove(); } if (this.dd) { this.dd.unreg(); this.dd = null; } if (this.proxy) { this.proxy.remove(); } if (this.repeater) { this.repeater.purgeListeners(); } } }); //backwards compat Ext.form.Spinner = Ext.ux.Spinner;