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