|
1 <?xml version="1.0"?> |
|
2 |
|
3 <!-- This Source Code Form is subject to the terms of the Mozilla Public |
|
4 - License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
|
6 |
|
7 <!DOCTYPE bindings [ |
|
8 <!ENTITY % datetimepickerDTD SYSTEM "chrome://global/locale/datetimepicker.dtd"> |
|
9 %datetimepickerDTD; |
|
10 ]> |
|
11 |
|
12 <bindings id="timepickerBindings" |
|
13 xmlns="http://www.mozilla.org/xbl" |
|
14 xmlns:html="http://www.w3.org/1999/xhtml" |
|
15 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
16 xmlns:xbl="http://www.mozilla.org/xbl"> |
|
17 |
|
18 <binding id="datetimepicker-base" |
|
19 extends="chrome://global/content/bindings/general.xml#basecontrol"> |
|
20 |
|
21 <resources> |
|
22 <stylesheet src="chrome://global/content/textbox.css"/> |
|
23 <stylesheet src="chrome://global/skin/textbox.css"/> |
|
24 <stylesheet src="chrome://global/skin/dropmarker.css"/> |
|
25 <stylesheet src="chrome://global/skin/datetimepicker.css"/> |
|
26 </resources> |
|
27 |
|
28 <content align="center"> |
|
29 <xul:hbox class="datetimepicker-input-box" align="center" |
|
30 xbl:inherits="context"> |
|
31 <xul:hbox class="textbox-input-box datetimepicker-input-subbox" align="center"> |
|
32 <html:input class="datetimepicker-input textbox-input" anonid="input-one" |
|
33 size="2" maxlength="2" |
|
34 xbl:inherits="disabled,readonly"/> |
|
35 </xul:hbox> |
|
36 <xul:label anonid="sep-first" class="datetimepicker-separator" value=":"/> |
|
37 <xul:hbox class="textbox-input-box datetimepicker-input-subbox" align="center"> |
|
38 <html:input class="datetimepicker-input textbox-input" anonid="input-two" |
|
39 size="2" maxlength="2" |
|
40 xbl:inherits="disabled,readonly"/> |
|
41 </xul:hbox> |
|
42 <xul:label anonid="sep-second" class="datetimepicker-separator" value=":"/> |
|
43 <xul:hbox class="textbox-input-box datetimepicker-input-subbox" align="center"> |
|
44 <html:input class="datetimepicker-input textbox-input" anonid="input-three" |
|
45 size="2" maxlength="2" |
|
46 xbl:inherits="disabled,readonly"/> |
|
47 </xul:hbox> |
|
48 <xul:hbox class="textbox-input-box datetimepicker-input-subbox" align="center"> |
|
49 <html:input class="datetimepicker-input textbox-input" anonid="input-ampm" |
|
50 size="2" maxlength="2" |
|
51 xbl:inherits="disabled,readonly"/> |
|
52 </xul:hbox> |
|
53 </xul:hbox> |
|
54 <xul:spinbuttons anonid="buttons" xbl:inherits="disabled" |
|
55 onup="this.parentNode._increaseOrDecrease(1);" |
|
56 ondown="this.parentNode._increaseOrDecrease(-1);"/> |
|
57 </content> |
|
58 |
|
59 <implementation> |
|
60 <field name="_dateValue">null</field> |
|
61 <field name="_fieldOne"> |
|
62 document.getAnonymousElementByAttribute(this, "anonid", "input-one"); |
|
63 </field> |
|
64 <field name="_fieldTwo"> |
|
65 document.getAnonymousElementByAttribute(this, "anonid", "input-two"); |
|
66 </field> |
|
67 <field name="_fieldThree"> |
|
68 document.getAnonymousElementByAttribute(this, "anonid", "input-three"); |
|
69 </field> |
|
70 <field name="_fieldAMPM"> |
|
71 document.getAnonymousElementByAttribute(this, "anonid", "input-ampm"); |
|
72 </field> |
|
73 <field name="_separatorFirst"> |
|
74 document.getAnonymousElementByAttribute(this, "anonid", "sep-first"); |
|
75 </field> |
|
76 <field name="_separatorSecond"> |
|
77 document.getAnonymousElementByAttribute(this, "anonid", "sep-second"); |
|
78 </field> |
|
79 <field name="_lastFocusedField">null</field> |
|
80 <field name="_hasEntry">true</field> |
|
81 <field name="_valueEntered">false</field> |
|
82 <field name="attachedControl">null</field> |
|
83 |
|
84 <property name="_currentField" readonly="true"> |
|
85 <getter> |
|
86 var focusedInput = document.activeElement; |
|
87 if (focusedInput == this._fieldOne || |
|
88 focusedInput == this._fieldTwo || |
|
89 focusedInput == this._fieldThree || |
|
90 focusedInput == this._fieldAMPM) |
|
91 return focusedInput; |
|
92 return this._lastFocusedField || this._fieldOne; |
|
93 </getter> |
|
94 </property> |
|
95 |
|
96 <property name="dateValue" onget="return new Date(this._dateValue);"> |
|
97 <setter> |
|
98 <![CDATA[ |
|
99 if (!(val instanceof Date)) |
|
100 throw "Invalid Date"; |
|
101 |
|
102 this._setValueNoSync(val); |
|
103 if (this.attachedControl) |
|
104 this.attachedControl._setValueNoSync(val); |
|
105 return val; |
|
106 ]]> |
|
107 </setter> |
|
108 </property> |
|
109 |
|
110 <property name="readOnly" onset="if (val) this.setAttribute('readonly', 'true'); |
|
111 else this.removeAttribute('readonly'); return val;" |
|
112 onget="return this.getAttribute('readonly') == 'true';"/> |
|
113 |
|
114 <method name="_fireEvent"> |
|
115 <parameter name="aEventName"/> |
|
116 <parameter name="aTarget"/> |
|
117 <body> |
|
118 var event = document.createEvent("Events"); |
|
119 event.initEvent(aEventName, true, true); |
|
120 return !aTarget.dispatchEvent(event); |
|
121 </body> |
|
122 </method> |
|
123 |
|
124 <method name="_setValueOnChange"> |
|
125 <parameter name="aField"/> |
|
126 <body> |
|
127 <![CDATA[ |
|
128 if (!this._hasEntry) |
|
129 return; |
|
130 |
|
131 if (aField == this._fieldOne || |
|
132 aField == this._fieldTwo || |
|
133 aField == this._fieldThree) { |
|
134 var value = Number(aField.value); |
|
135 if (isNaN(value)) |
|
136 value = 0; |
|
137 |
|
138 value = this._constrainValue(aField, value, true); |
|
139 this._setFieldValue(aField, value); |
|
140 } |
|
141 ]]> |
|
142 </body> |
|
143 </method> |
|
144 |
|
145 <method name="_init"> |
|
146 <body/> |
|
147 </method> |
|
148 |
|
149 <constructor> |
|
150 this._init(); |
|
151 |
|
152 var cval = this.getAttribute("value"); |
|
153 if (cval) { |
|
154 try { |
|
155 this.value = cval; |
|
156 return; |
|
157 } catch (ex) { } |
|
158 } |
|
159 this.dateValue = new Date(); |
|
160 </constructor> |
|
161 |
|
162 <destructor> |
|
163 if (this.attachedControl) { |
|
164 this.attachedControl.attachedControl = null; |
|
165 this.attachedControl = null; |
|
166 } |
|
167 </destructor> |
|
168 |
|
169 </implementation> |
|
170 |
|
171 <handlers> |
|
172 <handler event="focus" phase="capturing"> |
|
173 <![CDATA[ |
|
174 var target = event.originalTarget; |
|
175 if (target == this._fieldOne || |
|
176 target == this._fieldTwo || |
|
177 target == this._fieldThree || |
|
178 target == this._fieldAMPM) |
|
179 this._lastFocusedField = target; |
|
180 ]]> |
|
181 </handler> |
|
182 |
|
183 <handler event="keypress"> |
|
184 <![CDATA[ |
|
185 if (this._hasEntry && event.charCode && |
|
186 this._currentField != this._fieldAMPM && |
|
187 ! (event.altKey || event.ctrlKey || event.metaKey) && |
|
188 (event.charCode < 48 || event.charCode > 57)) |
|
189 event.preventDefault(); |
|
190 ]]> |
|
191 </handler> |
|
192 |
|
193 <handler event="keypress" keycode="VK_UP"> |
|
194 if (this._hasEntry) |
|
195 this._increaseOrDecrease(1); |
|
196 </handler> |
|
197 <handler event="keypress" keycode="VK_DOWN"> |
|
198 if (this._hasEntry) |
|
199 this._increaseOrDecrease(-1); |
|
200 </handler> |
|
201 |
|
202 <handler event="input"> |
|
203 this._valueEntered = true; |
|
204 </handler> |
|
205 |
|
206 <handler event="change"> |
|
207 this._setValueOnChange(event.originalTarget); |
|
208 </handler> |
|
209 </handlers> |
|
210 |
|
211 </binding> |
|
212 |
|
213 <binding id="timepicker" |
|
214 extends="chrome://global/content/bindings/datetimepicker.xml#datetimepicker-base"> |
|
215 |
|
216 <implementation> |
|
217 <field name="is24HourClock">false</field> |
|
218 <field name="hourLeadingZero">false</field> |
|
219 <field name="minuteLeadingZero">true</field> |
|
220 <field name="secondLeadingZero">true</field> |
|
221 <field name="amIndicator">"AM"</field> |
|
222 <field name="pmIndicator">"PM"</field> |
|
223 |
|
224 <field name="hourField">null</field> |
|
225 <field name="minuteField">null</field> |
|
226 <field name="secondField">null</field> |
|
227 |
|
228 <property name="value"> |
|
229 <getter> |
|
230 <![CDATA[ |
|
231 var minute = this._dateValue.getMinutes(); |
|
232 if (minute < 10) |
|
233 minute = "0" + minute; |
|
234 |
|
235 var second = this._dateValue.getSeconds(); |
|
236 if (second < 10) |
|
237 second = "0" + second; |
|
238 return this._dateValue.getHours() + ":" + minute + ":" + second; |
|
239 ]]> |
|
240 </getter> |
|
241 <setter> |
|
242 <![CDATA[ |
|
243 var items = val.match(/^([0-9]{1,2})\:([0-9]{1,2})\:?([0-9]{1,2})?$/); |
|
244 if (!items) |
|
245 throw "Invalid Time"; |
|
246 |
|
247 var dt = this.dateValue; |
|
248 dt.setHours(items[1]); |
|
249 dt.setMinutes(items[2]); |
|
250 dt.setSeconds(items[3] ? items[3] : 0); |
|
251 this.dateValue = dt; |
|
252 return val; |
|
253 ]]> |
|
254 </setter> |
|
255 </property> |
|
256 <property name="hour" onget="return this._dateValue.getHours();"> |
|
257 <setter> |
|
258 <![CDATA[ |
|
259 var valnum = Number(val); |
|
260 if (isNaN(valnum) || valnum < 0 || valnum > 23) |
|
261 throw "Invalid Hour"; |
|
262 this._setFieldValue(this.hourField, valnum); |
|
263 return val; |
|
264 ]]> |
|
265 </setter> |
|
266 </property> |
|
267 <property name="minute" onget="return this._dateValue.getMinutes();"> |
|
268 <setter> |
|
269 <![CDATA[ |
|
270 var valnum = Number(val); |
|
271 if (isNaN(valnum) || valnum < 0 || valnum > 59) |
|
272 throw "Invalid Minute"; |
|
273 this._setFieldValue(this.minuteField, valnum); |
|
274 return val; |
|
275 ]]> |
|
276 </setter> |
|
277 </property> |
|
278 <property name="second" onget="return this._dateValue.getSeconds();"> |
|
279 <setter> |
|
280 <![CDATA[ |
|
281 var valnum = Number(val); |
|
282 if (isNaN(valnum) || valnum < 0 || valnum > 59) |
|
283 throw "Invalid Second"; |
|
284 this._setFieldValue(this.secondField, valnum); |
|
285 return val; |
|
286 ]]> |
|
287 </setter> |
|
288 </property> |
|
289 <property name="isPM"> |
|
290 <getter> |
|
291 <![CDATA[ |
|
292 return (this.hour >= 12); |
|
293 ]]> |
|
294 </getter> |
|
295 <setter> |
|
296 <![CDATA[ |
|
297 if (val) { |
|
298 if (this.hour < 12) |
|
299 this.hour += 12; |
|
300 } |
|
301 else if (this.hour >= 12) |
|
302 this.hour -= 12; |
|
303 return val; |
|
304 ]]> |
|
305 </setter> |
|
306 </property> |
|
307 <property name="hideSeconds"> |
|
308 <getter> |
|
309 return (this.getAttribute("hideseconds") == "true"); |
|
310 </getter> |
|
311 <setter> |
|
312 if (val) |
|
313 this.setAttribute("hideseconds", "true"); |
|
314 else |
|
315 this.removeAttribute("hideseconds"); |
|
316 if (this.secondField) |
|
317 this.secondField.parentNode.collapsed = val; |
|
318 this._separatorSecond.collapsed = val; |
|
319 return val; |
|
320 </setter> |
|
321 </property> |
|
322 <property name="increment"> |
|
323 <getter> |
|
324 <![CDATA[ |
|
325 var increment = this.getAttribute("increment"); |
|
326 increment = Number(increment); |
|
327 if (isNaN(increment) || increment <= 0 || increment >= 60) |
|
328 return 1; |
|
329 return increment; |
|
330 ]]> |
|
331 </getter> |
|
332 <setter> |
|
333 <![CDATA[ |
|
334 if (typeof val == "number") |
|
335 this.setAttribute("increment", val); |
|
336 return val; |
|
337 ]]> |
|
338 </setter> |
|
339 </property> |
|
340 |
|
341 <method name="_setValueNoSync"> |
|
342 <parameter name="aValue"/> |
|
343 <body> |
|
344 <![CDATA[ |
|
345 var dt = new Date(aValue); |
|
346 if (!isNaN(dt)) { |
|
347 this._dateValue = dt; |
|
348 this.setAttribute("value", this.value); |
|
349 this._updateUI(this.hourField, this.hour); |
|
350 this._updateUI(this.minuteField, this.minute); |
|
351 this._updateUI(this.secondField, this.second); |
|
352 } |
|
353 ]]> |
|
354 </body> |
|
355 </method> |
|
356 <method name="_increaseOrDecrease"> |
|
357 <parameter name="aDir"/> |
|
358 <body> |
|
359 <![CDATA[ |
|
360 if (this.disabled || this.readOnly) |
|
361 return; |
|
362 |
|
363 var field = this._currentField; |
|
364 if (this._valueEntered) |
|
365 this._setValueOnChange(field); |
|
366 |
|
367 if (field == this._fieldAMPM) { |
|
368 this.isPM = !this.isPM; |
|
369 this._fireEvent("change", this); |
|
370 } |
|
371 else { |
|
372 var oldval; |
|
373 var change = aDir; |
|
374 if (field == this.hourField) { |
|
375 oldval = this.hour; |
|
376 } |
|
377 else if (field == this.minuteField) { |
|
378 oldval = this.minute; |
|
379 change *= this.increment; |
|
380 } |
|
381 else if (field == this.secondField) { |
|
382 oldval = this.second; |
|
383 } |
|
384 |
|
385 var newval = this._constrainValue(field, oldval + change, false); |
|
386 |
|
387 if (field == this.hourField) |
|
388 this.hour = newval; |
|
389 else if (field == this.minuteField) |
|
390 this.minute = newval; |
|
391 else if (field == this.secondField) |
|
392 this.second = newval; |
|
393 |
|
394 if (oldval != newval) |
|
395 this._fireEvent("change", this); |
|
396 } |
|
397 field.select(); |
|
398 ]]> |
|
399 </body> |
|
400 </method> |
|
401 <method name="_setFieldValue"> |
|
402 <parameter name="aField"/> |
|
403 <parameter name="aValue"/> |
|
404 <body> |
|
405 <![CDATA[ |
|
406 if (aField == this.hourField) |
|
407 this._dateValue.setHours(aValue); |
|
408 else if (aField == this.minuteField) |
|
409 this._dateValue.setMinutes(aValue); |
|
410 else if (aField == this.secondField) |
|
411 this._dateValue.setSeconds(aValue); |
|
412 |
|
413 this.setAttribute("value", this.value); |
|
414 this._updateUI(aField, aValue); |
|
415 |
|
416 if (this.attachedControl) |
|
417 this.attachedControl._setValueNoSync(this._dateValue); |
|
418 ]]> |
|
419 </body> |
|
420 </method> |
|
421 <method name="_updateUI"> |
|
422 <parameter name="aField"/> |
|
423 <parameter name="aValue"/> |
|
424 <body> |
|
425 <![CDATA[ |
|
426 this._valueEntered = false; |
|
427 |
|
428 var prependZero = false; |
|
429 if (aField == this.hourField) { |
|
430 prependZero = this.hourLeadingZero; |
|
431 if (!this.is24HourClock) { |
|
432 if (aValue >= 12) { |
|
433 if (aValue > 12) |
|
434 aValue -= 12; |
|
435 this._fieldAMPM.value = this.pmIndicator; |
|
436 } |
|
437 else { |
|
438 if (aValue == 0) |
|
439 aValue = 12; |
|
440 this._fieldAMPM.value = this.amIndicator; |
|
441 } |
|
442 } |
|
443 } |
|
444 else if (aField == this.minuteField) { |
|
445 prependZero = this.minuteLeadingZero; |
|
446 } |
|
447 else if (aField == this.secondField) { |
|
448 prependZero = this.secondLeadingZero; |
|
449 } |
|
450 |
|
451 if (prependZero && aValue < 10) |
|
452 aField.value = "0" + aValue; |
|
453 else |
|
454 aField.value = aValue; |
|
455 ]]> |
|
456 </body> |
|
457 </method> |
|
458 <method name="_constrainValue"> |
|
459 <parameter name="aField"/> |
|
460 <parameter name="aValue"/> |
|
461 <parameter name="aNoWrap"/> |
|
462 <body> |
|
463 <![CDATA[ |
|
464 // aNoWrap is true when the user entered a value, so just |
|
465 // constrain within limits. If false, the value is being |
|
466 // incremented or decremented, so wrap around values |
|
467 var max = (aField == this.hourField) ? 24 : 60; |
|
468 if (aValue < 0) |
|
469 return aNoWrap ? 0 : max + aValue; |
|
470 if (aValue >= max) |
|
471 return aNoWrap ? max - 1 : aValue - max; |
|
472 return aValue; |
|
473 ]]> |
|
474 </body> |
|
475 </method> |
|
476 <method name="_init"> |
|
477 <body> |
|
478 <![CDATA[ |
|
479 this.hourField = this._fieldOne; |
|
480 this.minuteField = this._fieldTwo; |
|
481 this.secondField = this._fieldThree; |
|
482 |
|
483 var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/; |
|
484 |
|
485 var pmTime = new Date(2000,0,1,16,7,9).toLocaleFormat("%X"); |
|
486 var numberFields = pmTime.match(numberOrder); |
|
487 if (numberFields) { |
|
488 this._separatorFirst.value = numberFields[3]; |
|
489 this._separatorSecond.value = numberFields[5]; |
|
490 if (Number(numberFields[2]) > 12) |
|
491 this.is24HourClock = true; |
|
492 else |
|
493 this.pmIndicator = numberFields[1] || numberFields[7]; |
|
494 } |
|
495 |
|
496 var amTime = new Date(2000,0,1,1,7,9).toLocaleFormat("%X"); |
|
497 numberFields = amTime.match(numberOrder); |
|
498 if (numberFields) { |
|
499 this.hourLeadingZero = (numberFields[2].length > 1); |
|
500 this.minuteLeadingZero = (numberFields[4].length > 1); |
|
501 this.secondLeadingZero = (numberFields[6].length > 1); |
|
502 |
|
503 if (!this.is24HourClock) { |
|
504 this.amIndicator = numberFields[1] || numberFields[7]; |
|
505 if (numberFields[1]) { |
|
506 var mfield = this._fieldAMPM.parentNode; |
|
507 var mcontainer = mfield.parentNode; |
|
508 mcontainer.insertBefore(mfield, mcontainer.firstChild); |
|
509 } |
|
510 var size = (numberFields[1] || numberFields[7]).length; |
|
511 if (this.pmIndicator.length > size) |
|
512 size = this.pmIndicator.length; |
|
513 this._fieldAMPM.size = size; |
|
514 this._fieldAMPM.maxLength = size; |
|
515 } |
|
516 else { |
|
517 this._fieldAMPM.parentNode.collapsed = true; |
|
518 } |
|
519 } |
|
520 |
|
521 this.hideSeconds = this.hideSeconds; |
|
522 ]]> |
|
523 </body> |
|
524 </method> |
|
525 </implementation> |
|
526 |
|
527 <handlers> |
|
528 <handler event="keypress"> |
|
529 <![CDATA[ |
|
530 // just allow any printable character to switch the AM/PM state |
|
531 if (event.charCode && !this.disabled && !this.readOnly && |
|
532 this._currentField == this._fieldAMPM) { |
|
533 this.isPM = !this.isPM; |
|
534 this._fieldAMPM.select(); |
|
535 this._fireEvent("change", this); |
|
536 event.preventDefault(); |
|
537 } |
|
538 ]]> |
|
539 </handler> |
|
540 </handlers> |
|
541 |
|
542 </binding> |
|
543 |
|
544 <binding id="datepicker" |
|
545 extends="chrome://global/content/bindings/datetimepicker.xml#datetimepicker-base"> |
|
546 |
|
547 <implementation> |
|
548 <field name="yearLeadingZero">false</field> |
|
549 <field name="monthLeadingZero">true</field> |
|
550 <field name="dateLeadingZero">true</field> |
|
551 |
|
552 <field name="yearField"/> |
|
553 <field name="monthField"/> |
|
554 <field name="dateField"/> |
|
555 |
|
556 <property name="value"> |
|
557 <getter> |
|
558 <![CDATA[ |
|
559 var month = this._dateValue.getMonth(); |
|
560 month = (month < 9) ? month = "0" + ++month : month + 1; |
|
561 |
|
562 var date = this._dateValue.getDate(); |
|
563 if (date < 10) |
|
564 date = "0" + date; |
|
565 return this._dateValue.getFullYear() + "-" + month + "-" + date; |
|
566 ]]> |
|
567 |
|
568 </getter> |
|
569 <setter> |
|
570 <![CDATA[ |
|
571 var results = val.match(/^([0-9]{1,4})\-([0-9]{1,2})\-([0-9]{1,2})$/); |
|
572 if (!results) |
|
573 throw "Invalid Date"; |
|
574 |
|
575 this.dateValue = new Date(results[1] + "/" + results[2] + "/" + results[3]); |
|
576 this.setAttribute("value", this.value); |
|
577 return val; |
|
578 ]]> |
|
579 </setter> |
|
580 </property> |
|
581 <property name="year" onget="return this._dateValue.getFullYear();"> |
|
582 <setter> |
|
583 <![CDATA[ |
|
584 var valnum = Number(val); |
|
585 if (isNaN(valnum) || valnum < 1 || valnum > 9999) |
|
586 throw "Invalid Year"; |
|
587 this._setFieldValue(this.yearField, valnum); |
|
588 return val; |
|
589 ]]> |
|
590 </setter> |
|
591 </property> |
|
592 <property name="month" onget="return this._dateValue.getMonth();"> |
|
593 <setter> |
|
594 <![CDATA[ |
|
595 var valnum = Number(val); |
|
596 if (isNaN(valnum) || valnum < 0 || valnum > 11) |
|
597 throw "Invalid Month"; |
|
598 this._setFieldValue(this.monthField, valnum); |
|
599 return val; |
|
600 ]]> |
|
601 </setter> |
|
602 </property> |
|
603 <property name="date" onget="return this._dateValue.getDate();"> |
|
604 <setter> |
|
605 <![CDATA[ |
|
606 var valnum = Number(val); |
|
607 if (isNaN(valnum) || valnum < 1 || valnum > 31) |
|
608 throw "Invalid Date"; |
|
609 this._setFieldValue(this.dateField, valnum); |
|
610 return val; |
|
611 ]]> |
|
612 </setter> |
|
613 </property> |
|
614 <property name="open" onget="return false;" onset="return val;"/> |
|
615 |
|
616 <property name="displayedMonth" onget="return this.month;" |
|
617 onset="this.month = val; return val;"/> |
|
618 <property name="displayedYear" onget="return this.year;" |
|
619 onset="this.year = val; return val;"/> |
|
620 |
|
621 <method name="_setValueNoSync"> |
|
622 <parameter name="aValue"/> |
|
623 <body> |
|
624 <![CDATA[ |
|
625 var dt = new Date(aValue); |
|
626 if (!isNaN(dt)) { |
|
627 this._dateValue = dt; |
|
628 this.setAttribute("value", this.value); |
|
629 this._updateUI(this.yearField, this.year); |
|
630 this._updateUI(this.monthField, this.month); |
|
631 this._updateUI(this.dateField, this.date); |
|
632 } |
|
633 ]]> |
|
634 </body> |
|
635 </method> |
|
636 <method name="_increaseOrDecrease"> |
|
637 <parameter name="aDir"/> |
|
638 <body> |
|
639 <![CDATA[ |
|
640 if (this.disabled || this.readOnly) |
|
641 return; |
|
642 |
|
643 var field = this._currentField; |
|
644 if (this._valueEntered) |
|
645 this._setValueOnChange(field); |
|
646 |
|
647 var oldval; |
|
648 if (field == this.yearField) |
|
649 oldval = this.year; |
|
650 else if (field == this.monthField) |
|
651 oldval = this.month; |
|
652 else if (field == this.dateField) |
|
653 oldval = this.date; |
|
654 |
|
655 var newval = this._constrainValue(field, oldval + aDir, false); |
|
656 |
|
657 if (field == this.yearField) |
|
658 this.year = newval; |
|
659 else if (field == this.monthField) |
|
660 this.month = newval; |
|
661 else if (field == this.dateField) |
|
662 this.date = newval; |
|
663 |
|
664 if (oldval != newval) |
|
665 this._fireEvent("change", this); |
|
666 field.select(); |
|
667 ]]> |
|
668 </body> |
|
669 </method> |
|
670 <method name="_setFieldValue"> |
|
671 <parameter name="aField"/> |
|
672 <parameter name="aValue"/> |
|
673 <body> |
|
674 <![CDATA[ |
|
675 if (aField == this.yearField) { |
|
676 var oldDate = this.date; |
|
677 this._dateValue.setFullYear(aValue); |
|
678 if (oldDate != this.date) { |
|
679 this._dateValue.setDate(0); |
|
680 this._updateUI(this.dateField, this.date); |
|
681 } |
|
682 } |
|
683 else if (aField == this.monthField) { |
|
684 var oldDate = this.date; |
|
685 this._dateValue.setMonth(aValue); |
|
686 if (oldDate != this.date) { |
|
687 this._dateValue.setDate(0); |
|
688 this._updateUI(this.dateField, this.date); |
|
689 } |
|
690 } |
|
691 else if (aField == this.dateField) { |
|
692 this._dateValue.setDate(aValue); |
|
693 } |
|
694 |
|
695 this.setAttribute("value", this.value); |
|
696 this._updateUI(aField, aValue); |
|
697 |
|
698 if (this.attachedControl) |
|
699 this.attachedControl._setValueNoSync(this._dateValue); |
|
700 ]]> |
|
701 </body> |
|
702 </method> |
|
703 <method name="_updateUI"> |
|
704 <parameter name="aField"/> |
|
705 <parameter name="aValue"/> |
|
706 <body> |
|
707 <![CDATA[ |
|
708 this._valueEntered = false; |
|
709 |
|
710 var prependZero = false; |
|
711 if (aField == this.yearField) { |
|
712 if (this.yearLeadingZero) { |
|
713 aField.value = ("000" + aValue).slice(-4); |
|
714 return; |
|
715 } |
|
716 } |
|
717 else if (aField == this.monthField) { |
|
718 aValue++; |
|
719 prependZero = this.monthLeadingZero; |
|
720 } |
|
721 else if (aField == this.dateField) { |
|
722 prependZero = this.dateLeadingZero; |
|
723 } |
|
724 if (prependZero && aValue < 10) |
|
725 aField.value = "0" + aValue; |
|
726 else |
|
727 aField.value = aValue; |
|
728 ]]> |
|
729 </body> |
|
730 </method> |
|
731 <method name="_constrainValue"> |
|
732 <parameter name="aField"/> |
|
733 <parameter name="aValue"/> |
|
734 <parameter name="aNoWrap"/> |
|
735 <body> |
|
736 <![CDATA[ |
|
737 // the month will be 1 to 12 if entered by the user, so subtract 1 |
|
738 if (aNoWrap && aField == this.monthField) |
|
739 aValue--; |
|
740 |
|
741 if (aField == this.dateField) { |
|
742 if (aValue < 1) |
|
743 return new Date(this.year, this.month + 1, 0).getDate(); |
|
744 |
|
745 var currentMonth = this.month; |
|
746 var dt = new Date(this.year, currentMonth, aValue); |
|
747 return (dt.getMonth() != currentMonth ? 1 : aValue); |
|
748 } |
|
749 var min = (aField == this.monthField) ? 0 : 1; |
|
750 var max = (aField == this.monthField) ? 11 : 9999; |
|
751 if (aValue < min) |
|
752 return aNoWrap ? min : max; |
|
753 if (aValue > max) |
|
754 return aNoWrap ? max : min; |
|
755 return aValue; |
|
756 ]]> |
|
757 </body> |
|
758 </method> |
|
759 <method name="_init"> |
|
760 <body> |
|
761 <![CDATA[ |
|
762 // We'll default to YYYY/MM/DD to start. |
|
763 var yfield = "input-one"; |
|
764 var mfield = "input-two"; |
|
765 var dfield = "input-three"; |
|
766 var twoDigitYear = false; |
|
767 this.yearLeadingZero = true; |
|
768 this.monthLeadingZero = true; |
|
769 this.dateLeadingZero = true; |
|
770 |
|
771 var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/; |
|
772 |
|
773 var dt = new Date(2002,9,4).toLocaleFormat("%x"); |
|
774 var numberFields = dt.match(numberOrder); |
|
775 if (numberFields) { |
|
776 this._separatorFirst.value = numberFields[3]; |
|
777 this._separatorSecond.value = numberFields[5]; |
|
778 |
|
779 var yi = 2, mi = 4, di = 6; |
|
780 |
|
781 for (var i = 1; i < numberFields.length; i++) { |
|
782 switch (Number(numberFields[i])) { |
|
783 case 2: |
|
784 twoDigitYear = true; // fall through |
|
785 case 2002: |
|
786 yi = i; |
|
787 yfield = (i == 2 ? "input-one" : |
|
788 (i == 4 ? "input-two" : "input-three")); |
|
789 break; |
|
790 case 9, 10: |
|
791 mi = i; |
|
792 mfield = (i == 2 ? "input-one" : |
|
793 (i == 4 ? "input-two" : "input-three")); |
|
794 break; |
|
795 case 4: |
|
796 di = i; |
|
797 dfield = (i == 2 ? "input-one" : |
|
798 (i == 4 ? "input-two" : "input-three")); |
|
799 break; |
|
800 } |
|
801 } |
|
802 |
|
803 this.yearLeadingZero = (numberFields[yi].length > 1); |
|
804 this.monthLeadingZero = (numberFields[mi].length > 1); |
|
805 this.dateLeadingZero = (numberFields[di].length > 1); |
|
806 } |
|
807 |
|
808 this.yearField = document.getAnonymousElementByAttribute(this, "anonid", yfield); |
|
809 if (!twoDigitYear) |
|
810 this.yearField.parentNode.classList.add("datetimepicker-input-subbox", "datetimepicker-year"); |
|
811 this.monthField = document.getAnonymousElementByAttribute(this, "anonid", mfield); |
|
812 this.dateField = document.getAnonymousElementByAttribute(this, "anonid", dfield); |
|
813 |
|
814 this._fieldAMPM.parentNode.collapsed = true; |
|
815 this.yearField.size = twoDigitYear ? 2 : 4; |
|
816 this.yearField.maxLength = twoDigitYear ? 2 : 4; |
|
817 ]]> |
|
818 </body> |
|
819 </method> |
|
820 </implementation> |
|
821 |
|
822 </binding> |
|
823 |
|
824 <binding id="datepicker-grid" |
|
825 extends="chrome://global/content/bindings/datetimepicker.xml#datepicker"> |
|
826 |
|
827 <content> |
|
828 <vbox class="datepicker-mainbox" |
|
829 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|
830 <hbox class="datepicker-monthbox" align="center"> |
|
831 <button class="datepicker-previous datepicker-button" type="repeat" |
|
832 xbl:inherits="disabled" |
|
833 oncommand="document.getBindingParent(this)._increaseOrDecreaseMonth(-1);"/> |
|
834 <spacer flex="1"/> |
|
835 <deck anonid="monthlabeldeck"> |
|
836 <label class="datepicker-gridlabel"/> |
|
837 <label class="datepicker-gridlabel"/> |
|
838 <label class="datepicker-gridlabel"/> |
|
839 <label class="datepicker-gridlabel"/> |
|
840 <label class="datepicker-gridlabel"/> |
|
841 <label class="datepicker-gridlabel"/> |
|
842 <label class="datepicker-gridlabel"/> |
|
843 <label class="datepicker-gridlabel"/> |
|
844 <label class="datepicker-gridlabel"/> |
|
845 <label class="datepicker-gridlabel"/> |
|
846 <label class="datepicker-gridlabel"/> |
|
847 <label class="datepicker-gridlabel"/> |
|
848 </deck> |
|
849 <label anonid="yearlabel" class="datepicker-gridlabel"/> |
|
850 <spacer flex="1"/> |
|
851 <button class="datepicker-next datepicker-button" type="repeat" |
|
852 xbl:inherits="disabled" |
|
853 oncommand="document.getBindingParent(this)._increaseOrDecreaseMonth(1);"/> |
|
854 </hbox> |
|
855 <grid class="datepicker-grid" role="grid"> |
|
856 <columns> |
|
857 <column class="datepicker-gridrow" flex="1"/> |
|
858 <column class="datepicker-gridrow" flex="1"/> |
|
859 <column class="datepicker-gridrow" flex="1"/> |
|
860 <column class="datepicker-gridrow" flex="1"/> |
|
861 <column class="datepicker-gridrow" flex="1"/> |
|
862 <column class="datepicker-gridrow" flex="1"/> |
|
863 <column class="datepicker-gridrow" flex="1"/> |
|
864 </columns> |
|
865 <rows anonid="datebox"> |
|
866 <row anonid="dayofweekbox"> |
|
867 <label class="datepicker-weeklabel" role="columnheader"/> |
|
868 <label class="datepicker-weeklabel" role="columnheader"/> |
|
869 <label class="datepicker-weeklabel" role="columnheader"/> |
|
870 <label class="datepicker-weeklabel" role="columnheader"/> |
|
871 <label class="datepicker-weeklabel" role="columnheader"/> |
|
872 <label class="datepicker-weeklabel" role="columnheader"/> |
|
873 <label class="datepicker-weeklabel" role="columnheader"/> |
|
874 </row> |
|
875 <row> |
|
876 <label class="datepicker-gridlabel" role="gridcell"/> |
|
877 <label class="datepicker-gridlabel" role="gridcell"/> |
|
878 <label class="datepicker-gridlabel" role="gridcell"/> |
|
879 <label class="datepicker-gridlabel" role="gridcell"/> |
|
880 <label class="datepicker-gridlabel" role="gridcell"/> |
|
881 <label class="datepicker-gridlabel" role="gridcell"/> |
|
882 <label class="datepicker-gridlabel" role="gridcell"/> |
|
883 </row> |
|
884 <row> |
|
885 <label class="datepicker-gridlabel" role="gridcell"/> |
|
886 <label class="datepicker-gridlabel" role="gridcell"/> |
|
887 <label class="datepicker-gridlabel" role="gridcell"/> |
|
888 <label class="datepicker-gridlabel" role="gridcell"/> |
|
889 <label class="datepicker-gridlabel" role="gridcell"/> |
|
890 <label class="datepicker-gridlabel" role="gridcell"/> |
|
891 <label class="datepicker-gridlabel" role="gridcell"/> |
|
892 </row> |
|
893 <row> |
|
894 <label class="datepicker-gridlabel" role="gridcell"/> |
|
895 <label class="datepicker-gridlabel" role="gridcell"/> |
|
896 <label class="datepicker-gridlabel" role="gridcell"/> |
|
897 <label class="datepicker-gridlabel" role="gridcell"/> |
|
898 <label class="datepicker-gridlabel" role="gridcell"/> |
|
899 <label class="datepicker-gridlabel" role="gridcell"/> |
|
900 <label class="datepicker-gridlabel" role="gridcell"/> |
|
901 </row> |
|
902 <row> |
|
903 <label class="datepicker-gridlabel" role="gridcell"/> |
|
904 <label class="datepicker-gridlabel" role="gridcell"/> |
|
905 <label class="datepicker-gridlabel" role="gridcell"/> |
|
906 <label class="datepicker-gridlabel" role="gridcell"/> |
|
907 <label class="datepicker-gridlabel" role="gridcell"/> |
|
908 <label class="datepicker-gridlabel" role="gridcell"/> |
|
909 <label class="datepicker-gridlabel" role="gridcell"/> |
|
910 </row> |
|
911 <row> |
|
912 <label class="datepicker-gridlabel" role="gridcell"/> |
|
913 <label class="datepicker-gridlabel" role="gridcell"/> |
|
914 <label class="datepicker-gridlabel" role="gridcell"/> |
|
915 <label class="datepicker-gridlabel" role="gridcell"/> |
|
916 <label class="datepicker-gridlabel" role="gridcell"/> |
|
917 <label class="datepicker-gridlabel" role="gridcell"/> |
|
918 <label class="datepicker-gridlabel" role="gridcell"/> |
|
919 </row> |
|
920 <row> |
|
921 <label class="datepicker-gridlabel" role="gridcell"/> |
|
922 <label class="datepicker-gridlabel" role="gridcell"/> |
|
923 <label class="datepicker-gridlabel" role="gridcell"/> |
|
924 <label class="datepicker-gridlabel" role="gridcell"/> |
|
925 <label class="datepicker-gridlabel" role="gridcell"/> |
|
926 <label class="datepicker-gridlabel" role="gridcell"/> |
|
927 <label class="datepicker-gridlabel" role="gridcell"/> |
|
928 </row> |
|
929 </rows> |
|
930 </grid> |
|
931 </vbox> |
|
932 </content> |
|
933 |
|
934 <implementation> |
|
935 <field name="_hasEntry">false</field> |
|
936 <field name="_weekStart">&firstdayofweek.default;</field> |
|
937 <field name="_displayedDate">null</field> |
|
938 <field name="_todayItem">null</field> |
|
939 |
|
940 <field name="yearField"> |
|
941 document.getAnonymousElementByAttribute(this, "anonid", "yearlabel"); |
|
942 </field> |
|
943 <field name="monthField"> |
|
944 document.getAnonymousElementByAttribute(this, "anonid", "monthlabeldeck"); |
|
945 </field> |
|
946 <field name="dateField"> |
|
947 document.getAnonymousElementByAttribute(this, "anonid", "datebox"); |
|
948 </field> |
|
949 |
|
950 <field name="_selectedItem">null</field> |
|
951 |
|
952 <property name="selectedItem" onget="return this._selectedItem"> |
|
953 <setter> |
|
954 <![CDATA[ |
|
955 if (!val.value) |
|
956 return val; |
|
957 if (val.parentNode.parentNode != this.dateField) |
|
958 return val; |
|
959 |
|
960 if (this._selectedItem) |
|
961 this._selectedItem.removeAttribute("selected"); |
|
962 this._selectedItem = val; |
|
963 val.setAttribute("selected", "true"); |
|
964 this._displayedDate.setDate(val.value); |
|
965 return val; |
|
966 ]]> |
|
967 </setter> |
|
968 </property> |
|
969 |
|
970 <property name="displayedMonth"> |
|
971 <getter> |
|
972 return this._displayedDate.getMonth(); |
|
973 </getter> |
|
974 <setter> |
|
975 this._updateUI(this.monthField, val, true); |
|
976 return val; |
|
977 </setter> |
|
978 </property> |
|
979 <property name="displayedYear"> |
|
980 <getter> |
|
981 return this._displayedDate.getFullYear(); |
|
982 </getter> |
|
983 <setter> |
|
984 this._updateUI(this.yearField, val, true); |
|
985 return val; |
|
986 </setter> |
|
987 </property> |
|
988 |
|
989 <method name="_init"> |
|
990 <body> |
|
991 <![CDATA[ |
|
992 var monthLabel = this.monthField.firstChild; |
|
993 var tempDate = new Date(2005, 0, 1); |
|
994 for (var month = 0; month < 12; month++) { |
|
995 tempDate.setMonth(month); |
|
996 monthLabel.setAttribute("value", tempDate.toLocaleFormat("%B")); |
|
997 monthLabel = monthLabel.nextSibling; |
|
998 } |
|
999 |
|
1000 var fdow = Number(this.getAttribute("firstdayofweek")); |
|
1001 if (!isNaN(fdow) && fdow >= 0 && fdow <= 6) |
|
1002 this._weekStart = fdow; |
|
1003 |
|
1004 var weekbox = document.getAnonymousElementByAttribute(this, "anonid", "dayofweekbox").childNodes; |
|
1005 var date = new Date(); |
|
1006 date.setDate(date.getDate() - (date.getDay() - this._weekStart)); |
|
1007 for (var i = 0; i < weekbox.length; i++) { |
|
1008 weekbox[i].value = date.toLocaleFormat("%a").charAt(0); |
|
1009 date.setDate(date.getDate() + 1); |
|
1010 } |
|
1011 ]]> |
|
1012 </body> |
|
1013 </method> |
|
1014 <method name="_setValueNoSync"> |
|
1015 <parameter name="aValue"/> |
|
1016 <body> |
|
1017 <![CDATA[ |
|
1018 var dt = new Date(aValue); |
|
1019 if (!isNaN(dt)) { |
|
1020 this._dateValue = dt; |
|
1021 this.setAttribute("value", this.value); |
|
1022 this._updateUI(); |
|
1023 } |
|
1024 ]]> |
|
1025 </body> |
|
1026 </method> |
|
1027 <method name="_updateUI"> |
|
1028 <parameter name="aField"/> |
|
1029 <parameter name="aValue"/> |
|
1030 <parameter name="aCheckMonth"/> |
|
1031 <body> |
|
1032 <![CDATA[ |
|
1033 var date; |
|
1034 var currentMonth; |
|
1035 if (aCheckMonth) { |
|
1036 if (!this._displayedDate) |
|
1037 this._displayedDate = this.dateValue; |
|
1038 |
|
1039 var expectedMonth = aValue; |
|
1040 if (aField == this.monthField) { |
|
1041 this._displayedDate.setMonth(aValue); |
|
1042 } |
|
1043 else { |
|
1044 expectedMonth = this._displayedDate.getMonth(); |
|
1045 this._displayedDate.setFullYear(aValue); |
|
1046 } |
|
1047 |
|
1048 if (expectedMonth != -1 && expectedMonth != 12 && |
|
1049 expectedMonth != this._displayedDate.getMonth()) { |
|
1050 // If the month isn't what was expected, then the month overflowed. |
|
1051 // Setting the date to 0 will go back to the last day of the right month. |
|
1052 this._displayedDate.setDate(0); |
|
1053 } |
|
1054 |
|
1055 date = new Date(this._displayedDate); |
|
1056 currentMonth = this._displayedDate.getMonth(); |
|
1057 } |
|
1058 else { |
|
1059 var samemonth = (this._displayedDate && |
|
1060 this._displayedDate.getMonth() == this.month && |
|
1061 this._displayedDate.getFullYear() == this.year); |
|
1062 if (samemonth) { |
|
1063 var items = this.dateField.getElementsByAttribute("value", this.date); |
|
1064 if (items.length) |
|
1065 this.selectedItem = items[0]; |
|
1066 return; |
|
1067 } |
|
1068 |
|
1069 date = this.dateValue; |
|
1070 this._displayedDate = new Date(date); |
|
1071 currentMonth = this.month; |
|
1072 } |
|
1073 |
|
1074 if (this._todayItem) { |
|
1075 this._todayItem.removeAttribute("today"); |
|
1076 this._todayItem = null; |
|
1077 } |
|
1078 |
|
1079 if (this._selectedItem) { |
|
1080 this._selectedItem.removeAttribute("selected"); |
|
1081 this._selectedItem = null; |
|
1082 } |
|
1083 |
|
1084 // Update the month and year title |
|
1085 this.monthField.selectedIndex = currentMonth; |
|
1086 this.yearField.setAttribute("value", date.getFullYear()); |
|
1087 |
|
1088 date.setDate(1); |
|
1089 var firstWeekday = (7 + date.getDay() - this._weekStart) % 7; |
|
1090 date.setDate(date.getDate() - firstWeekday); |
|
1091 |
|
1092 var today = new Date(); |
|
1093 var datebox = this.dateField; |
|
1094 for (var k = 1; k < datebox.childNodes.length; k++) { |
|
1095 var row = datebox.childNodes[k]; |
|
1096 for (var i = 0; i < 7; i++) { |
|
1097 var item = row.childNodes[i]; |
|
1098 |
|
1099 if (currentMonth == date.getMonth()) { |
|
1100 item.value = date.getDate(); |
|
1101 |
|
1102 // highlight today |
|
1103 if (this._isSameDay(today, date)) { |
|
1104 this._todayItem = item; |
|
1105 item.setAttribute("today", "true"); |
|
1106 } |
|
1107 |
|
1108 // highlight the selected date |
|
1109 if (this._isSameDay(this._dateValue, date)) { |
|
1110 this._selectedItem = item; |
|
1111 item.setAttribute("selected", "true"); |
|
1112 } |
|
1113 } |
|
1114 else { |
|
1115 item.value = ""; |
|
1116 } |
|
1117 |
|
1118 date.setDate(date.getDate() + 1); |
|
1119 } |
|
1120 } |
|
1121 |
|
1122 this._fireEvent("monthchange", this); |
|
1123 if (this.hasAttribute("monthchange")) { |
|
1124 var fn = new Function("event", aTarget.getAttribute("onmonthchange")); |
|
1125 fn.call(aTarget, event); |
|
1126 } |
|
1127 ]]> |
|
1128 </body> |
|
1129 </method> |
|
1130 <method name="_increaseOrDecreaseDateFromEvent"> |
|
1131 <parameter name="aEvent"/> |
|
1132 <parameter name="aDiff"/> |
|
1133 <body> |
|
1134 <![CDATA[ |
|
1135 if (aEvent.originalTarget == this && !this.disabled && !this.readOnly) { |
|
1136 var newdate = this.dateValue; |
|
1137 newdate.setDate(newdate.getDate() + aDiff); |
|
1138 this.dateValue = newdate; |
|
1139 this._fireEvent("change", this); |
|
1140 } |
|
1141 aEvent.stopPropagation(); |
|
1142 aEvent.preventDefault(); |
|
1143 ]]> |
|
1144 </body> |
|
1145 </method> |
|
1146 <method name="_increaseOrDecreaseMonth"> |
|
1147 <parameter name="aDir"/> |
|
1148 <body> |
|
1149 <![CDATA[ |
|
1150 if (!this.disabled) { |
|
1151 var month = this._displayedDate ? this._displayedDate.getMonth() : |
|
1152 this.month; |
|
1153 this._updateUI(this.monthField, month + aDir, true); |
|
1154 } |
|
1155 ]]> |
|
1156 </body> |
|
1157 </method> |
|
1158 <method name="_isSameDay"> |
|
1159 <parameter name="aDate1"/> |
|
1160 <parameter name="aDate2"/> |
|
1161 <body> |
|
1162 <![CDATA[ |
|
1163 return (aDate1 && aDate2 && |
|
1164 aDate1.getDate() == aDate2.getDate() && |
|
1165 aDate1.getMonth() == aDate2.getMonth() && |
|
1166 aDate1.getFullYear() == aDate2.getFullYear()); |
|
1167 ]]> |
|
1168 </body> |
|
1169 </method> |
|
1170 |
|
1171 </implementation> |
|
1172 |
|
1173 <handlers> |
|
1174 <handler event="click"> |
|
1175 <![CDATA[ |
|
1176 if (event.button != 0 || this.disabled || this.readOnly) |
|
1177 return; |
|
1178 |
|
1179 var target = event.originalTarget; |
|
1180 if (target.classList.contains("datepicker-gridlabel") && |
|
1181 target != this.selectedItem) { |
|
1182 this.selectedItem = target; |
|
1183 this._dateValue = new Date(this._displayedDate); |
|
1184 if (this.attachedControl) |
|
1185 this.attachedControl._setValueNoSync(this._dateValue); |
|
1186 this._fireEvent("change", this); |
|
1187 |
|
1188 if (this.attachedControl && "open" in this.attachedControl) |
|
1189 this.attachedControl.open = false; // close the popup |
|
1190 } |
|
1191 ]]> |
|
1192 </handler> |
|
1193 <handler event="MozMousePixelScroll" preventdefault="true"/> |
|
1194 <handler event="DOMMouseScroll" preventdefault="true"> |
|
1195 <![CDATA[ |
|
1196 this._increaseOrDecreaseMonth(event.detail < 0 ? -1 : 1); |
|
1197 ]]> |
|
1198 </handler> |
|
1199 <handler event="keypress" keycode="VK_LEFT" |
|
1200 action="this._increaseOrDecreaseDateFromEvent(event, -1);"/> |
|
1201 <handler event="keypress" keycode="VK_RIGHT" |
|
1202 action="this._increaseOrDecreaseDateFromEvent(event, 1);"/> |
|
1203 <handler event="keypress" keycode="VK_UP" |
|
1204 action="this._increaseOrDecreaseDateFromEvent(event, -7);"/> |
|
1205 <handler event="keypress" keycode="VK_DOWN" |
|
1206 action="this._increaseOrDecreaseDateFromEvent(event, 7);"/> |
|
1207 <handler event="keypress" keycode="VK_PAGE_UP" preventdefault="true" |
|
1208 action="this._increaseOrDecreaseMonth(-1);"/> |
|
1209 <handler event="keypress" keycode="VK_PAGE_DOWN" preventdefault="true" |
|
1210 action="this._increaseOrDecreaseMonth(1);"/> |
|
1211 </handlers> |
|
1212 </binding> |
|
1213 |
|
1214 <binding id="datepicker-popup" display="xul:menu" |
|
1215 extends="chrome://global/content/bindings/datetimepicker.xml#datepicker"> |
|
1216 <content align="center"> |
|
1217 <xul:hbox class="textbox-input-box datetimepicker-input-box" align="center" |
|
1218 allowevents="true" xbl:inherits="context"> |
|
1219 <xul:hbox class="datetimepicker-input-subbox" align="baseline"> |
|
1220 <html:input class="datetimepicker-input textbox-input" anonid="input-one" |
|
1221 size="2" maxlength="2" |
|
1222 xbl:inherits="disabled,readonly"/> |
|
1223 </xul:hbox> |
|
1224 <xul:label anonid="sep-first" class="datetimepicker-separator" value=":"/> |
|
1225 <xul:hbox class="datetimepicker-input-subbox" align="baseline"> |
|
1226 <html:input class="datetimepicker-input textbox-input" anonid="input-two" |
|
1227 size="2" maxlength="2" |
|
1228 xbl:inherits="disabled,readonly"/> |
|
1229 </xul:hbox> |
|
1230 <xul:label anonid="sep-second" class="datetimepicker-separator" value=":"/> |
|
1231 <xul:hbox class="datetimepicker-input-subbox" align="center"> |
|
1232 <html:input class="datetimepicker-input textbox-input" anonid="input-three" |
|
1233 size="2" maxlength="2" |
|
1234 xbl:inherits="disabled,readonly"/> |
|
1235 </xul:hbox> |
|
1236 <xul:hbox class="datetimepicker-input-subbox" align="center"> |
|
1237 <html:input class="datetimepicker-input textbox-input" anonid="input-ampm" |
|
1238 size="2" maxlength="2" |
|
1239 xbl:inherits="disabled,readonly"/> |
|
1240 </xul:hbox> |
|
1241 </xul:hbox> |
|
1242 <xul:spinbuttons anonid="buttons" xbl:inherits="disabled" allowevents="true" |
|
1243 onup="this.parentNode._increaseOrDecrease(1);" |
|
1244 ondown="this.parentNode._increaseOrDecrease(-1);"/> |
|
1245 <xul:dropmarker class="datepicker-dropmarker" xbl:inherits="disabled"/> |
|
1246 <xul:panel onpopupshown="this.firstChild.focus();" level="top"> |
|
1247 <xul:datepicker anonid="grid" type="grid" class="datepicker-popupgrid" |
|
1248 xbl:inherits="disabled,readonly,firstdayofweek"/> |
|
1249 </xul:panel> |
|
1250 </content> |
|
1251 <implementation> |
|
1252 <constructor> |
|
1253 var grid = document.getAnonymousElementByAttribute(this, "anonid", "grid"); |
|
1254 this.attachedControl = grid; |
|
1255 grid.attachedControl = this; |
|
1256 grid._setValueNoSync(this._dateValue); |
|
1257 </constructor> |
|
1258 <property name="open" onget="return this.hasAttribute('open');"> |
|
1259 <setter> |
|
1260 <![CDATA[ |
|
1261 if (this.boxObject instanceof Components.interfaces.nsIMenuBoxObject) |
|
1262 this.boxObject.openMenu(val); |
|
1263 return val; |
|
1264 ]]> |
|
1265 </setter> |
|
1266 </property> |
|
1267 <property name="displayedMonth"> |
|
1268 <getter> |
|
1269 return document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedMonth; |
|
1270 </getter> |
|
1271 <setter> |
|
1272 document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedMonth = val; |
|
1273 return val; |
|
1274 </setter> |
|
1275 </property> |
|
1276 <property name="displayedYear"> |
|
1277 <getter> |
|
1278 return document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedYear; |
|
1279 </getter> |
|
1280 <setter> |
|
1281 document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedYear = val; |
|
1282 return val; |
|
1283 </setter> |
|
1284 </property> |
|
1285 </implementation> |
|
1286 </binding> |
|
1287 |
|
1288 </bindings> |