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