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