1 | define([ |
---|
2 | "dojo/_base/declare", // declare |
---|
3 | "dojo/keys", // keys keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW |
---|
4 | "dojo/_base/lang", // lang.hitch |
---|
5 | "dojo/sniff", // has("mozilla") |
---|
6 | "dojo/mouse", // mouse.wheel |
---|
7 | "dojo/on", |
---|
8 | "../typematic", |
---|
9 | "./RangeBoundTextBox", |
---|
10 | "dojo/text!./templates/Spinner.html", |
---|
11 | "./_TextBoxMixin" // selectInputText |
---|
12 | ], function(declare, keys, lang, has, mouse, on, typematic, RangeBoundTextBox, template, _TextBoxMixin){ |
---|
13 | |
---|
14 | // module: |
---|
15 | // dijit/form/_Spinner |
---|
16 | |
---|
17 | return declare("dijit.form._Spinner", RangeBoundTextBox, { |
---|
18 | // summary: |
---|
19 | // Mixin for validation widgets with a spinner. |
---|
20 | // description: |
---|
21 | // This class basically (conceptually) extends `dijit/form/ValidationTextBox`. |
---|
22 | // It modifies the template to have up/down arrows, and provides related handling code. |
---|
23 | |
---|
24 | // defaultTimeout: Number |
---|
25 | // Number of milliseconds before a held arrow key or up/down button becomes typematic |
---|
26 | defaultTimeout: 500, |
---|
27 | |
---|
28 | // minimumTimeout: Number |
---|
29 | // minimum number of milliseconds that typematic event fires when held key or button is held |
---|
30 | minimumTimeout: 10, |
---|
31 | |
---|
32 | // timeoutChangeRate: Number |
---|
33 | // Fraction of time used to change the typematic timer between events. |
---|
34 | // 1.0 means that each typematic event fires at defaultTimeout intervals. |
---|
35 | // Less than 1.0 means that each typematic event fires at an increasing faster rate. |
---|
36 | timeoutChangeRate: 0.90, |
---|
37 | |
---|
38 | // smallDelta: Number |
---|
39 | // Adjust the value by this much when spinning using the arrow keys/buttons |
---|
40 | smallDelta: 1, |
---|
41 | |
---|
42 | // largeDelta: Number |
---|
43 | // Adjust the value by this much when spinning using the PgUp/Dn keys |
---|
44 | largeDelta: 10, |
---|
45 | |
---|
46 | templateString: template, |
---|
47 | |
---|
48 | baseClass: "dijitTextBox dijitSpinner", |
---|
49 | |
---|
50 | // Set classes like dijitUpArrowButtonHover or dijitDownArrowButtonActive depending on |
---|
51 | // mouse action over specified node |
---|
52 | cssStateNodes: { |
---|
53 | "upArrowNode": "dijitUpArrowButton", |
---|
54 | "downArrowNode": "dijitDownArrowButton" |
---|
55 | }, |
---|
56 | |
---|
57 | adjust: function(val /*=====, delta =====*/){ |
---|
58 | // summary: |
---|
59 | // Overridable function used to adjust a primitive value(Number/Date/...) by the delta amount specified. |
---|
60 | // The val is adjusted in a way that makes sense to the object type. |
---|
61 | // val: Object |
---|
62 | // delta: Number |
---|
63 | // tags: |
---|
64 | // protected extension |
---|
65 | return val; |
---|
66 | }, |
---|
67 | |
---|
68 | _arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction, /*Number*/ increment){ |
---|
69 | // summary: |
---|
70 | // Handler for arrow button or arrow key being pressed |
---|
71 | if(this.disabled || this.readOnly){ |
---|
72 | return; |
---|
73 | } |
---|
74 | this._setValueAttr(this.adjust(this.get('value'), direction * increment), false); |
---|
75 | _TextBoxMixin.selectInputText(this.textbox, this.textbox.value.length); |
---|
76 | }, |
---|
77 | |
---|
78 | _arrowReleased: function(/*Node*/ /*===== node =====*/){ |
---|
79 | // summary: |
---|
80 | // Handler for arrow button or arrow key being released |
---|
81 | this._wheelTimer = null; |
---|
82 | }, |
---|
83 | |
---|
84 | _typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){ |
---|
85 | var inc = this.smallDelta; |
---|
86 | if(node == this.textbox){ |
---|
87 | var key = evt.keyCode; |
---|
88 | inc = (key == keys.PAGE_UP || key == keys.PAGE_DOWN) ? this.largeDelta : this.smallDelta; |
---|
89 | node = (key == keys.UP_ARROW || key == keys.PAGE_UP) ? this.upArrowNode : this.downArrowNode; |
---|
90 | } |
---|
91 | if(count == -1){ |
---|
92 | this._arrowReleased(node); |
---|
93 | } |
---|
94 | else{ |
---|
95 | this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1, inc); |
---|
96 | } |
---|
97 | }, |
---|
98 | |
---|
99 | _wheelTimer: null, |
---|
100 | _mouseWheeled: function(/*Event*/ evt){ |
---|
101 | // summary: |
---|
102 | // Mouse wheel listener where supported |
---|
103 | |
---|
104 | evt.stopPropagation(); |
---|
105 | evt.preventDefault(); |
---|
106 | // FIXME: Safari bubbles |
---|
107 | |
---|
108 | // be nice to DOH and scroll as much as the event says to |
---|
109 | var wheelDelta = evt.wheelDelta / 120; |
---|
110 | if(Math.floor(wheelDelta) != wheelDelta){ |
---|
111 | // If not an int multiple of 120, then its touchpad scrolling. |
---|
112 | // This can change very fast so just assume 1 wheel click to make it more manageable. |
---|
113 | wheelDelta = evt.wheelDelta > 0 ? 1 : -1; |
---|
114 | } |
---|
115 | var scrollAmount = evt.detail ? (evt.detail * -1) : wheelDelta; |
---|
116 | if(scrollAmount !== 0){ |
---|
117 | var node = this[(scrollAmount > 0 ? "upArrowNode" : "downArrowNode" )]; |
---|
118 | |
---|
119 | this._arrowPressed(node, scrollAmount, this.smallDelta); |
---|
120 | |
---|
121 | if(this._wheelTimer){ |
---|
122 | this._wheelTimer.remove(); |
---|
123 | } |
---|
124 | this._wheelTimer = this.defer(function(){ |
---|
125 | this._arrowReleased(node); |
---|
126 | }, 50); |
---|
127 | } |
---|
128 | }, |
---|
129 | |
---|
130 | _setConstraintsAttr: function(/*Object*/ constraints){ |
---|
131 | this.inherited(arguments); |
---|
132 | if(this.focusNode){ // not set when called from postMixInProperties |
---|
133 | if(this.constraints.min !== undefined){ |
---|
134 | this.focusNode.setAttribute("aria-valuemin", this.constraints.min); |
---|
135 | }else{ |
---|
136 | this.focusNode.removeAttribute("aria-valuemin"); |
---|
137 | } |
---|
138 | if(this.constraints.max !== undefined){ |
---|
139 | this.focusNode.setAttribute("aria-valuemax", this.constraints.max); |
---|
140 | }else{ |
---|
141 | this.focusNode.removeAttribute("aria-valuemax"); |
---|
142 | } |
---|
143 | } |
---|
144 | }, |
---|
145 | |
---|
146 | _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){ |
---|
147 | // summary: |
---|
148 | // Hook so set('value', ...) works. |
---|
149 | |
---|
150 | this.focusNode.setAttribute("aria-valuenow", value); |
---|
151 | this.inherited(arguments); |
---|
152 | }, |
---|
153 | |
---|
154 | postCreate: function(){ |
---|
155 | this.inherited(arguments); |
---|
156 | |
---|
157 | // extra listeners |
---|
158 | this.own( |
---|
159 | on(this.domNode, mouse.wheel, lang.hitch(this, "_mouseWheeled")), |
---|
160 | typematic.addListener(this.upArrowNode, this.textbox, {keyCode: keys.UP_ARROW, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout), |
---|
161 | typematic.addListener(this.downArrowNode, this.textbox, {keyCode: keys.DOWN_ARROW, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout), |
---|
162 | typematic.addListener(this.upArrowNode, this.textbox, {keyCode: keys.PAGE_UP, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout), |
---|
163 | typematic.addListener(this.downArrowNode, this.textbox, {keyCode: keys.PAGE_DOWN, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout) |
---|
164 | ); |
---|
165 | } |
---|
166 | }); |
---|
167 | }); |
---|