|
1 <?xml version="1.0"?> |
|
2 <!-- This Source Code Form is subject to the terms of the Mozilla Public |
|
3 - License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
|
5 |
|
6 |
|
7 <bindings id="numberboxBindings" |
|
8 xmlns="http://www.mozilla.org/xbl" |
|
9 xmlns:html="http://www.w3.org/1999/xhtml" |
|
10 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
11 xmlns:xbl="http://www.mozilla.org/xbl"> |
|
12 |
|
13 <binding id="numberbox" |
|
14 extends="chrome://global/content/bindings/textbox.xml#textbox"> |
|
15 |
|
16 <resources> |
|
17 <stylesheet src="chrome://global/skin/numberbox.css"/> |
|
18 </resources> |
|
19 |
|
20 <content> |
|
21 <xul:hbox class="textbox-input-box numberbox-input-box" flex="1" xbl:inherits="context,disabled,focused"> |
|
22 <html:input class="numberbox-input textbox-input" anonid="input" |
|
23 xbl:inherits="value,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/> |
|
24 </xul:hbox> |
|
25 <xul:spinbuttons anonid="buttons" xbl:inherits="disabled,hidden=hidespinbuttons"/> |
|
26 </content> |
|
27 |
|
28 <implementation> |
|
29 <field name="_valueEntered">false</field> |
|
30 <field name="_spinButtons">null</field> |
|
31 <field name="_value">0</field> |
|
32 <field name="decimalSymbol">"."</field> |
|
33 |
|
34 <property name="spinButtons" readonly="true"> |
|
35 <getter> |
|
36 <![CDATA[ |
|
37 if (!this._spinButtons) |
|
38 this._spinButtons = document.getAnonymousElementByAttribute(this, "anonid", "buttons"); |
|
39 return this._spinButtons; |
|
40 ]]> |
|
41 </getter> |
|
42 </property> |
|
43 |
|
44 <property name="value" onget="return '' + this.valueNumber" |
|
45 onset="return this.valueNumber = val;"/> |
|
46 |
|
47 <property name="valueNumber"> |
|
48 <getter> |
|
49 if (this._valueEntered) { |
|
50 var newval = this.inputField.value; |
|
51 newval = newval.replace(this.decimalSymbol, "."); |
|
52 this._validateValue(newval, false); |
|
53 } |
|
54 return this._value; |
|
55 </getter> |
|
56 <setter> |
|
57 this._validateValue(val, false); |
|
58 return val; |
|
59 </setter> |
|
60 </property> |
|
61 |
|
62 <property name="wrapAround"> |
|
63 <getter> |
|
64 <![CDATA[ |
|
65 return (this.getAttribute('wraparound') == 'true') |
|
66 ]]> |
|
67 </getter> |
|
68 <setter> |
|
69 <![CDATA[ |
|
70 if (val) |
|
71 this.setAttribute('wraparound', 'true'); |
|
72 else |
|
73 this.removeAttribute('wraparound'); |
|
74 this._enableDisableButtons(); |
|
75 return val; |
|
76 ]]> |
|
77 </setter> |
|
78 </property> |
|
79 |
|
80 <property name="min"> |
|
81 <getter> |
|
82 var min = this.getAttribute("min"); |
|
83 return min ? Number(min) : 0; |
|
84 </getter> |
|
85 <setter> |
|
86 <![CDATA[ |
|
87 if (typeof val == "number") { |
|
88 this.setAttribute("min", val); |
|
89 if (this.valueNumber < val) |
|
90 this._validateValue(val, false); |
|
91 } |
|
92 return val; |
|
93 ]]> |
|
94 </setter> |
|
95 </property> |
|
96 |
|
97 <property name="max"> |
|
98 <getter> |
|
99 var max = this.getAttribute("max"); |
|
100 return max ? Number(max) : Infinity; |
|
101 </getter> |
|
102 <setter> |
|
103 <![CDATA[ |
|
104 if (typeof val != "number") |
|
105 return val; |
|
106 var min = this.min; |
|
107 if (val < min) |
|
108 val = min; |
|
109 this.setAttribute("max", val); |
|
110 if (this.valueNumber > val) |
|
111 this._validateValue(val, false); |
|
112 return val; |
|
113 ]]> |
|
114 </setter> |
|
115 </property> |
|
116 |
|
117 <property name="decimalPlaces"> |
|
118 <getter> |
|
119 var places = this.getAttribute("decimalplaces"); |
|
120 return places ? Number(places) : 0; |
|
121 </getter> |
|
122 <setter> |
|
123 if (typeof val == "number") { |
|
124 this.setAttribute("decimalplaces", val); |
|
125 this._validateValue(this.valueNumber, false); |
|
126 } |
|
127 return val; |
|
128 </setter> |
|
129 </property> |
|
130 |
|
131 <property name="increment"> |
|
132 <getter> |
|
133 var increment = this.getAttribute("increment"); |
|
134 return increment ? Number(increment) : 1; |
|
135 </getter> |
|
136 <setter> |
|
137 <![CDATA[ |
|
138 if (typeof val == "number") |
|
139 this.setAttribute("increment", val); |
|
140 return val; |
|
141 ]]> |
|
142 </setter> |
|
143 </property> |
|
144 |
|
145 <method name="decrease"> |
|
146 <body> |
|
147 return this._validateValue(this.valueNumber - this.increment, true); |
|
148 </body> |
|
149 </method> |
|
150 |
|
151 <method name="increase"> |
|
152 <body> |
|
153 return this._validateValue(this.valueNumber + this.increment, true); |
|
154 </body> |
|
155 </method> |
|
156 |
|
157 <method name="_modifyUp"> |
|
158 <body> |
|
159 <![CDATA[ |
|
160 if (this.disabled || this.readOnly) |
|
161 return; |
|
162 var oldval = this.valueNumber; |
|
163 var newval = this.increase(); |
|
164 this.inputField.select(); |
|
165 if (oldval != newval) |
|
166 this._fireChange(); |
|
167 ]]> |
|
168 </body> |
|
169 </method> |
|
170 <method name="_modifyDown"> |
|
171 <body> |
|
172 <![CDATA[ |
|
173 if (this.disabled || this.readOnly) |
|
174 return; |
|
175 var oldval = this.valueNumber; |
|
176 var newval = this.decrease(); |
|
177 this.inputField.select(); |
|
178 if (oldval != newval) |
|
179 this._fireChange(); |
|
180 ]]> |
|
181 </body> |
|
182 </method> |
|
183 |
|
184 <method name="_enableDisableButtons"> |
|
185 <body> |
|
186 <![CDATA[ |
|
187 var buttons = this.spinButtons; |
|
188 if (this.wrapAround) { |
|
189 buttons.decreaseDisabled = buttons.increaseDisabled = false; |
|
190 } |
|
191 else if (this.disabled || this.readOnly) { |
|
192 buttons.decreaseDisabled = buttons.increaseDisabled = true; |
|
193 } |
|
194 else { |
|
195 buttons.decreaseDisabled = (this.valueNumber <= this.min); |
|
196 buttons.increaseDisabled = (this.valueNumber >= this.max); |
|
197 } |
|
198 ]]> |
|
199 </body> |
|
200 </method> |
|
201 |
|
202 <method name="_validateValue"> |
|
203 <parameter name="aValue"/> |
|
204 <parameter name="aIsIncDec"/> |
|
205 <body> |
|
206 <![CDATA[ |
|
207 aValue = Number(aValue) || 0; |
|
208 |
|
209 var min = this.min; |
|
210 var max = this.max; |
|
211 var wrapAround = this.wrapAround && |
|
212 min != -Infinity && max != Infinity; |
|
213 if (aValue < min) |
|
214 aValue = (aIsIncDec && wrapAround ? max : min); |
|
215 else if (aValue > max) |
|
216 aValue = (aIsIncDec && wrapAround ? min : max); |
|
217 |
|
218 var places = this.decimalPlaces; |
|
219 aValue = (places == Infinity) ? "" + aValue : aValue.toFixed(places); |
|
220 |
|
221 this._valueEntered = false; |
|
222 this._value = Number(aValue); |
|
223 this.inputField.value = aValue.replace(/\./, this.decimalSymbol); |
|
224 |
|
225 if (!wrapAround) |
|
226 this._enableDisableButtons(); |
|
227 |
|
228 return aValue; |
|
229 ]]> |
|
230 </body> |
|
231 </method> |
|
232 |
|
233 <method name="_fireChange"> |
|
234 <body> |
|
235 var evt = document.createEvent("Events"); |
|
236 evt.initEvent("change", true, true); |
|
237 this.dispatchEvent(evt); |
|
238 </body> |
|
239 </method> |
|
240 |
|
241 <constructor><![CDATA[ |
|
242 if (this.max < this.min) |
|
243 this.max = this.min; |
|
244 |
|
245 var dsymbol = (Number(5.4)).toLocaleString().match(/\D/); |
|
246 if (dsymbol != null) |
|
247 this.decimalSymbol = dsymbol[0]; |
|
248 |
|
249 var value = this.inputField.value || 0; |
|
250 this._validateValue(value, false); |
|
251 ]]></constructor> |
|
252 |
|
253 </implementation> |
|
254 |
|
255 <handlers> |
|
256 <handler event="input" phase="capturing"> |
|
257 this._valueEntered = true; |
|
258 </handler> |
|
259 |
|
260 <handler event="keypress"> |
|
261 <![CDATA[ |
|
262 if (!event.ctrlKey && !event.metaKey && !event.altKey && event.charCode) { |
|
263 if (event.charCode == this.decimalSymbol.charCodeAt(0) && |
|
264 this.decimalPlaces && |
|
265 String(this.inputField.value).indexOf(this.decimalSymbol) == -1) |
|
266 return; |
|
267 |
|
268 if (event.charCode == 45 && this.min < 0) |
|
269 return; |
|
270 |
|
271 if (event.charCode < 48 || event.charCode > 57) |
|
272 event.preventDefault(); |
|
273 } |
|
274 ]]> |
|
275 </handler> |
|
276 |
|
277 <handler event="keypress" keycode="VK_UP"> |
|
278 this._modifyUp(); |
|
279 </handler> |
|
280 |
|
281 <handler event="keypress" keycode="VK_DOWN"> |
|
282 this._modifyDown(); |
|
283 </handler> |
|
284 |
|
285 <handler event="up" preventdefault="true"> |
|
286 this._modifyUp(); |
|
287 </handler> |
|
288 |
|
289 <handler event="down" preventdefault="true"> |
|
290 this._modifyDown(); |
|
291 </handler> |
|
292 |
|
293 <handler event="change"> |
|
294 if (event.originalTarget == this.inputField) { |
|
295 var newval = this.inputField.value; |
|
296 newval = newval.replace(this.decimalSymbol, "."); |
|
297 this._validateValue(newval, false); |
|
298 } |
|
299 </handler> |
|
300 </handlers> |
|
301 |
|
302 </binding> |
|
303 |
|
304 </bindings> |