toolkit/content/widgets/datetimepicker.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial