Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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> |