Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 <?xml version="1.0"?>
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/. -->
7 <!DOCTYPE bindings [
8 <!ENTITY % datetimepickerDTD SYSTEM "chrome://global/locale/datetimepicker.dtd">
9 %datetimepickerDTD;
10 ]>
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">
18 <binding id="datetimepicker-base"
19 extends="chrome://global/content/bindings/general.xml#basecontrol">
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>
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>
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>
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>
96 <property name="dateValue" onget="return new Date(this._dateValue);">
97 <setter>
98 <![CDATA[
99 if (!(val instanceof Date))
100 throw "Invalid Date";
102 this._setValueNoSync(val);
103 if (this.attachedControl)
104 this.attachedControl._setValueNoSync(val);
105 return val;
106 ]]>
107 </setter>
108 </property>
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';"/>
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>
124 <method name="_setValueOnChange">
125 <parameter name="aField"/>
126 <body>
127 <![CDATA[
128 if (!this._hasEntry)
129 return;
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;
138 value = this._constrainValue(aField, value, true);
139 this._setFieldValue(aField, value);
140 }
141 ]]>
142 </body>
143 </method>
145 <method name="_init">
146 <body/>
147 </method>
149 <constructor>
150 this._init();
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>
162 <destructor>
163 if (this.attachedControl) {
164 this.attachedControl.attachedControl = null;
165 this.attachedControl = null;
166 }
167 </destructor>
169 </implementation>
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>
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>
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>
202 <handler event="input">
203 this._valueEntered = true;
204 </handler>
206 <handler event="change">
207 this._setValueOnChange(event.originalTarget);
208 </handler>
209 </handlers>
211 </binding>
213 <binding id="timepicker"
214 extends="chrome://global/content/bindings/datetimepicker.xml#datetimepicker-base">
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>
224 <field name="hourField">null</field>
225 <field name="minuteField">null</field>
226 <field name="secondField">null</field>
228 <property name="value">
229 <getter>
230 <![CDATA[
231 var minute = this._dateValue.getMinutes();
232 if (minute < 10)
233 minute = "0" + minute;
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";
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>
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;
363 var field = this._currentField;
364 if (this._valueEntered)
365 this._setValueOnChange(field);
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 }
385 var newval = this._constrainValue(field, oldval + change, false);
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;
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);
413 this.setAttribute("value", this.value);
414 this._updateUI(aField, aValue);
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;
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 }
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;
483 var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/;
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 }
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);
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 }
521 this.hideSeconds = this.hideSeconds;
522 ]]>
523 </body>
524 </method>
525 </implementation>
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>
542 </binding>
544 <binding id="datepicker"
545 extends="chrome://global/content/bindings/datetimepicker.xml#datetimepicker-base">
547 <implementation>
548 <field name="yearLeadingZero">false</field>
549 <field name="monthLeadingZero">true</field>
550 <field name="dateLeadingZero">true</field>
552 <field name="yearField"/>
553 <field name="monthField"/>
554 <field name="dateField"/>
556 <property name="value">
557 <getter>
558 <![CDATA[
559 var month = this._dateValue.getMonth();
560 month = (month < 9) ? month = "0" + ++month : month + 1;
562 var date = this._dateValue.getDate();
563 if (date < 10)
564 date = "0" + date;
565 return this._dateValue.getFullYear() + "-" + month + "-" + date;
566 ]]>
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";
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;"/>
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;"/>
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;
643 var field = this._currentField;
644 if (this._valueEntered)
645 this._setValueOnChange(field);
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;
655 var newval = this._constrainValue(field, oldval + aDir, false);
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;
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 }
695 this.setAttribute("value", this.value);
696 this._updateUI(aField, aValue);
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;
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--;
741 if (aField == this.dateField) {
742 if (aValue < 1)
743 return new Date(this.year, this.month + 1, 0).getDate();
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;
771 var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/;
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];
779 var yi = 2, mi = 4, di = 6;
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 }
803 this.yearLeadingZero = (numberFields[yi].length > 1);
804 this.monthLeadingZero = (numberFields[mi].length > 1);
805 this.dateLeadingZero = (numberFields[di].length > 1);
806 }
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);
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>
822 </binding>
824 <binding id="datepicker-grid"
825 extends="chrome://global/content/bindings/datetimepicker.xml#datepicker">
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>
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>
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>
950 <field name="_selectedItem">null</field>
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;
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>
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>
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 }
1000 var fdow = Number(this.getAttribute("firstdayofweek"));
1001 if (!isNaN(fdow) && fdow >= 0 && fdow <= 6)
1002 this._weekStart = fdow;
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;
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 }
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 }
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 }
1069 date = this.dateValue;
1070 this._displayedDate = new Date(date);
1071 currentMonth = this.month;
1072 }
1074 if (this._todayItem) {
1075 this._todayItem.removeAttribute("today");
1076 this._todayItem = null;
1077 }
1079 if (this._selectedItem) {
1080 this._selectedItem.removeAttribute("selected");
1081 this._selectedItem = null;
1082 }
1084 // Update the month and year title
1085 this.monthField.selectedIndex = currentMonth;
1086 this.yearField.setAttribute("value", date.getFullYear());
1088 date.setDate(1);
1089 var firstWeekday = (7 + date.getDay() - this._weekStart) % 7;
1090 date.setDate(date.getDate() - firstWeekday);
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];
1099 if (currentMonth == date.getMonth()) {
1100 item.value = date.getDate();
1102 // highlight today
1103 if (this._isSameDay(today, date)) {
1104 this._todayItem = item;
1105 item.setAttribute("today", "true");
1106 }
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 }
1118 date.setDate(date.getDate() + 1);
1119 }
1120 }
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>
1171 </implementation>
1173 <handlers>
1174 <handler event="click">
1175 <![CDATA[
1176 if (event.button != 0 || this.disabled || this.readOnly)
1177 return;
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);
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>
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>
1288 </bindings>