Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / docs / source / Spinner.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.3.1
11  * Copyright(c) 2006-2010 Sencha Inc.
12  * licensing@sencha.com
13  * http://www.sencha.com/license
14  */
15 <div id="cls-Ext.ux.Spinner"></div>/**
16  * @class Ext.ux.Spinner
17  * @extends Ext.util.Observable
18  * Creates a Spinner control utilized by Ext.ux.form.SpinnerField
19  */
20 Ext.ux.Spinner = Ext.extend(Ext.util.Observable, {
21     incrementValue: 1,
22     alternateIncrementValue: 5,
23     triggerClass: 'x-form-spinner-trigger',
24     splitterClass: 'x-form-spinner-splitter',
25     alternateKey: Ext.EventObject.shiftKey,
26     defaultValue: 0,
27     accelerate: false,
28
29     constructor: function(config){
30         Ext.ux.Spinner.superclass.constructor.call(this, config);
31         Ext.apply(this, config);
32         this.mimicing = false;
33     },
34
35     init: function(field){
36         this.field = field;
37
38         field.afterMethod('onRender', this.doRender, this);
39         field.afterMethod('onEnable', this.doEnable, this);
40         field.afterMethod('onDisable', this.doDisable, this);
41         field.afterMethod('afterRender', this.doAfterRender, this);
42         field.afterMethod('onResize', this.doResize, this);
43         field.afterMethod('onFocus', this.doFocus, this);
44         field.beforeMethod('onDestroy', this.doDestroy, this);
45     },
46
47     doRender: function(ct, position){
48         var el = this.el = this.field.getEl();
49         var f = this.field;
50
51         if (!f.wrap) {
52             f.wrap = this.wrap = el.wrap({
53                 cls: "x-form-field-wrap"
54             });
55         }
56         else {
57             this.wrap = f.wrap.addClass('x-form-field-wrap');
58         }
59
60         this.trigger = this.wrap.createChild({
61             tag: "img",
62             src: Ext.BLANK_IMAGE_URL,
63             cls: "x-form-trigger " + this.triggerClass
64         });
65
66         if (!f.width) {
67             this.wrap.setWidth(el.getWidth() + this.trigger.getWidth());
68         }
69
70         this.splitter = this.wrap.createChild({
71             tag: 'div',
72             cls: this.splitterClass,
73             style: 'width:13px; height:2px;'
74         });
75         this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show();
76
77         this.proxy = this.trigger.createProxy('', this.splitter, true);
78         this.proxy.addClass("x-form-spinner-proxy");
79         this.proxy.setStyle('left', '0px');
80         this.proxy.setSize(14, 1);
81         this.proxy.hide();
82         this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {
83             dragElId: this.proxy.id
84         });
85
86         this.initTrigger();
87         this.initSpinner();
88     },
89
90     doAfterRender: function(){
91         var y;
92         if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) {
93             this.el.position();
94             this.el.setY(y);
95         }
96     },
97
98     doEnable: function(){
99         if (this.wrap) {
100             this.disabled = false;
101             this.wrap.removeClass(this.field.disabledClass);
102         }
103     },
104
105     doDisable: function(){
106         if (this.wrap) {
107                 this.disabled = true;
108             this.wrap.addClass(this.field.disabledClass);
109             this.el.removeClass(this.field.disabledClass);
110         }
111     },
112
113     doResize: function(w, h){
114         if (typeof w == 'number') {
115             this.el.setWidth(w - this.trigger.getWidth());
116         }
117         this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
118     },
119
120     doFocus: function(){
121         if (!this.mimicing) {
122             this.wrap.addClass('x-trigger-wrap-focus');
123             this.mimicing = true;
124             Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {
125                 delay: 10
126             });
127             this.el.on('keydown', this.checkTab, this);
128         }
129     },
130
131     // private
132     checkTab: function(e){
133         if (e.getKey() == e.TAB) {
134             this.triggerBlur();
135         }
136     },
137
138     // private
139     mimicBlur: function(e){
140         if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) {
141             this.triggerBlur();
142         }
143     },
144
145     // private
146     triggerBlur: function(){
147         this.mimicing = false;
148         Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);
149         this.el.un("keydown", this.checkTab, this);
150         this.field.beforeBlur();
151         this.wrap.removeClass('x-trigger-wrap-focus');
152         this.field.onBlur.call(this.field);
153     },
154
155     initTrigger: function(){
156         this.trigger.addClassOnOver('x-form-trigger-over');
157         this.trigger.addClassOnClick('x-form-trigger-click');
158     },
159
160     initSpinner: function(){
161         this.field.addEvents({
162             'spin': true,
163             'spinup': true,
164             'spindown': true
165         });
166
167         this.keyNav = new Ext.KeyNav(this.el, {
168             "up": function(e){
169                 e.preventDefault();
170                 this.onSpinUp();
171             },
172
173             "down": function(e){
174                 e.preventDefault();
175                 this.onSpinDown();
176             },
177
178             "pageUp": function(e){
179                 e.preventDefault();
180                 this.onSpinUpAlternate();
181             },
182
183             "pageDown": function(e){
184                 e.preventDefault();
185                 this.onSpinDownAlternate();
186             },
187
188             scope: this
189         });
190
191         this.repeater = new Ext.util.ClickRepeater(this.trigger, {
192             accelerate: this.accelerate
193         });
194         this.field.mon(this.repeater, "click", this.onTriggerClick, this, {
195             preventDefault: true
196         });
197
198         this.field.mon(this.trigger, {
199             mouseover: this.onMouseOver,
200             mouseout: this.onMouseOut,
201             mousemove: this.onMouseMove,
202             mousedown: this.onMouseDown,
203             mouseup: this.onMouseUp,
204             scope: this,
205             preventDefault: true
206         });
207
208         this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this);
209
210         this.dd.setXConstraint(0, 0, 10)
211         this.dd.setYConstraint(1500, 1500, 10);
212         this.dd.endDrag = this.endDrag.createDelegate(this);
213         this.dd.startDrag = this.startDrag.createDelegate(this);
214         this.dd.onDrag = this.onDrag.createDelegate(this);
215     },
216
217     onMouseOver: function(){
218         if (this.disabled) {
219             return;
220         }
221         var middle = this.getMiddle();
222         this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
223         this.trigger.addClass(this.tmpHoverClass);
224     },
225
226     //private
227     onMouseOut: function(){
228         this.trigger.removeClass(this.tmpHoverClass);
229     },
230
231     //private
232     onMouseMove: function(){
233         if (this.disabled) {
234             return;
235         }
236         var middle = this.getMiddle();
237         if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") ||
238         ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) {
239         }
240     },
241
242     //private
243     onMouseDown: function(){
244         if (this.disabled) {
245             return;
246         }
247         var middle = this.getMiddle();
248         this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
249         this.trigger.addClass(this.tmpClickClass);
250     },
251
252     //private
253     onMouseUp: function(){
254         this.trigger.removeClass(this.tmpClickClass);
255     },
256
257     //private
258     onTriggerClick: function(){
259         if (this.disabled || this.el.dom.readOnly) {
260             return;
261         }
262         var middle = this.getMiddle();
263         var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
264         this['onSpin' + ud]();
265     },
266
267     //private
268     getMiddle: function(){
269         var t = this.trigger.getTop();
270         var h = this.trigger.getHeight();
271         var middle = t + (h / 2);
272         return middle;
273     },
274
275     //private
276     //checks if control is allowed to spin
277     isSpinnable: function(){
278         if (this.disabled || this.el.dom.readOnly) {
279             Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly
280             return false;
281         }
282         return true;
283     },
284
285     handleMouseWheel: function(e){
286         //disable scrolling when not focused
287         if (this.wrap.hasClass('x-trigger-wrap-focus') == false) {
288             return;
289         }
290
291         var delta = e.getWheelDelta();
292         if (delta > 0) {
293             this.onSpinUp();
294             e.stopEvent();
295         }
296         else
297             if (delta < 0) {
298                 this.onSpinDown();
299                 e.stopEvent();
300             }
301     },
302
303     //private
304     startDrag: function(){
305         this.proxy.show();
306         this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
307     },
308
309     //private
310     endDrag: function(){
311         this.proxy.hide();
312     },
313
314     //private
315     onDrag: function(){
316         if (this.disabled) {
317             return;
318         }
319         var y = Ext.fly(this.dd.getDragEl()).getTop();
320         var ud = '';
321
322         if (this._previousY > y) {
323             ud = 'Up';
324         } //up
325         if (this._previousY < y) {
326             ud = 'Down';
327         } //down
328         if (ud != '') {
329             this['onSpin' + ud]();
330         }
331
332         this._previousY = y;
333     },
334
335     //private
336     onSpinUp: function(){
337         if (this.isSpinnable() == false) {
338             return;
339         }
340         if (Ext.EventObject.shiftKey == true) {
341             this.onSpinUpAlternate();
342             return;
343         }
344         else {
345             this.spin(false, false);
346         }
347         this.field.fireEvent("spin", this);
348         this.field.fireEvent("spinup", this);
349     },
350
351     //private
352     onSpinDown: function(){
353         if (this.isSpinnable() == false) {
354             return;
355         }
356         if (Ext.EventObject.shiftKey == true) {
357             this.onSpinDownAlternate();
358             return;
359         }
360         else {
361             this.spin(true, false);
362         }
363         this.field.fireEvent("spin", this);
364         this.field.fireEvent("spindown", this);
365     },
366
367     //private
368     onSpinUpAlternate: function(){
369         if (this.isSpinnable() == false) {
370             return;
371         }
372         this.spin(false, true);
373         this.field.fireEvent("spin", this);
374         this.field.fireEvent("spinup", this);
375     },
376
377     //private
378     onSpinDownAlternate: function(){
379         if (this.isSpinnable() == false) {
380             return;
381         }
382         this.spin(true, true);
383         this.field.fireEvent("spin", this);
384         this.field.fireEvent("spindown", this);
385     },
386
387     spin: function(down, alternate){
388         var v = parseFloat(this.field.getValue());
389         var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
390         (down == true) ? v -= incr : v += incr;
391
392         v = (isNaN(v)) ? this.defaultValue : v;
393         v = this.fixBoundries(v);
394         this.field.setRawValue(v);
395     },
396
397     fixBoundries: function(value){
398         var v = value;
399
400         if (this.field.minValue != undefined && v < this.field.minValue) {
401             v = this.field.minValue;
402         }
403         if (this.field.maxValue != undefined && v > this.field.maxValue) {
404             v = this.field.maxValue;
405         }
406
407         return this.fixPrecision(v);
408     },
409
410     // private
411     fixPrecision: function(value){
412         var nan = isNaN(value);
413         if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) {
414             return nan ? '' : value;
415         }
416         return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision));
417     },
418
419     doDestroy: function(){
420         if (this.trigger) {
421             this.trigger.remove();
422         }
423         if (this.wrap) {
424             this.wrap.remove();
425             delete this.field.wrap;
426         }
427
428         if (this.splitter) {
429             this.splitter.remove();
430         }
431
432         if (this.dd) {
433             this.dd.unreg();
434             this.dd = null;
435         }
436
437         if (this.proxy) {
438             this.proxy.remove();
439         }
440
441         if (this.repeater) {
442             this.repeater.purgeListeners();
443         }
444         if (this.mimicing){
445             Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);
446         }
447     }
448 });
449
450 //backwards compat
451 Ext.form.Spinner = Ext.ux.Spinner;</pre>    
452 </body>
453 </html>