1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 28 #include "core/html/shadow/DateTimeFieldElements.h" 29 30 #include "core/html/DateTimeFieldsState.h" 31 #include "core/platform/DateComponents.h" 32 #include "core/platform/LocalizedStrings.h" 33 #include "wtf/CurrentTime.h" 34 #include "wtf/DateMath.h" 35 36 namespace WebCore { 37 38 DateTimeAMPMFieldElement::DateTimeAMPMFieldElement(Document* document, FieldOwner& fieldOwner, const Vector<String>& ampmLabels) 39 : DateTimeSymbolicFieldElement(document, fieldOwner, ampmLabels, 0, 1) 40 { 41 } 42 43 PassRefPtr<DateTimeAMPMFieldElement> DateTimeAMPMFieldElement::create(Document* document, FieldOwner& fieldOwner, const Vector<String>& ampmLabels) 44 { 45 DEFINE_STATIC_LOCAL(AtomicString, ampmPsuedoId, ("-webkit-datetime-edit-ampm-field", AtomicString::ConstructFromLiteral)); 46 RefPtr<DateTimeAMPMFieldElement> field = adoptRef(new DateTimeAMPMFieldElement(document, fieldOwner, ampmLabels)); 47 field->initialize(ampmPsuedoId, AXAMPMFieldText()); 48 return field.release(); 49 } 50 51 void DateTimeAMPMFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 52 { 53 if (hasValue()) 54 dateTimeFieldsState.setAMPM(valueAsInteger() ? DateTimeFieldsState::AMPMValuePM : DateTimeFieldsState::AMPMValueAM); 55 else 56 dateTimeFieldsState.setAMPM(DateTimeFieldsState::AMPMValueEmpty); 57 } 58 59 void DateTimeAMPMFieldElement::setValueAsDate(const DateComponents& date) 60 { 61 setValueAsInteger(date.hour() >= 12 ? 1 : 0); 62 } 63 64 void DateTimeAMPMFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 65 { 66 if (dateTimeFieldsState.hasAMPM()) 67 setValueAsInteger(dateTimeFieldsState.ampm()); 68 else 69 setEmptyValue(); 70 } 71 72 // ---------------------------- 73 74 DateTimeDayFieldElement::DateTimeDayFieldElement(Document* document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) 75 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(1, 31), placeholder) 76 { 77 } 78 79 PassRefPtr<DateTimeDayFieldElement> DateTimeDayFieldElement::create(Document* document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) 80 { 81 DEFINE_STATIC_LOCAL(AtomicString, dayPsuedoId, ("-webkit-datetime-edit-day-field", AtomicString::ConstructFromLiteral)); 82 RefPtr<DateTimeDayFieldElement> field = adoptRef(new DateTimeDayFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); 83 field->initialize(dayPsuedoId, AXDayOfMonthFieldText()); 84 return field.release(); 85 } 86 87 void DateTimeDayFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 88 { 89 dateTimeFieldsState.setDayOfMonth(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 90 } 91 92 void DateTimeDayFieldElement::setValueAsDate(const DateComponents& date) 93 { 94 setValueAsInteger(date.monthDay()); 95 } 96 97 void DateTimeDayFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 98 { 99 if (!dateTimeFieldsState.hasDayOfMonth()) { 100 setEmptyValue(); 101 return; 102 } 103 104 const unsigned value = dateTimeFieldsState.dayOfMonth(); 105 if (range().isInRange(static_cast<int>(value))) { 106 setValueAsInteger(value); 107 return; 108 } 109 110 setEmptyValue(); 111 } 112 113 // ---------------------------- 114 115 DateTimeHourFieldElementBase::DateTimeHourFieldElementBase(Document* document, FieldOwner& fieldOwner, const Range& range, const Range& hardLimits, const Step& step) 116 : DateTimeNumericFieldElement(document, fieldOwner, range, hardLimits, "--", step) 117 { 118 } 119 120 void DateTimeHourFieldElementBase::initialize() 121 { 122 DEFINE_STATIC_LOCAL(AtomicString, hourPsuedoId, ("-webkit-datetime-edit-hour-field", AtomicString::ConstructFromLiteral)); 123 DateTimeNumericFieldElement::initialize(hourPsuedoId, AXHourFieldText()); 124 } 125 126 void DateTimeHourFieldElementBase::setValueAsDate(const DateComponents& date) 127 { 128 setValueAsInteger(date.hour()); 129 } 130 131 void DateTimeHourFieldElementBase::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 132 { 133 if (!dateTimeFieldsState.hasHour()) { 134 setEmptyValue(); 135 return; 136 } 137 138 const int hour12 = dateTimeFieldsState.hour(); 139 if (hour12 < 1 || hour12 > 12) { 140 setEmptyValue(); 141 return; 142 } 143 144 if (dateTimeFieldsState.ampm() == DateTimeFieldsState::AMPMValuePM) 145 setValueAsInteger((hour12 + 12) % 24); 146 else 147 setValueAsInteger(hour12 % 12); 148 } 149 // ---------------------------- 150 151 DateTimeHour11FieldElement::DateTimeHour11FieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 152 : DateTimeHourFieldElementBase(document, fieldOwner, range, Range(0, 11), step) 153 { 154 } 155 156 PassRefPtr<DateTimeHour11FieldElement> DateTimeHour11FieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) 157 { 158 ASSERT(hour23Range.minimum >= 0); 159 ASSERT(hour23Range.maximum <= 23); 160 ASSERT(hour23Range.minimum <= hour23Range.maximum); 161 Range range(0, 11); 162 if (hour23Range.maximum < 12) 163 range = hour23Range; 164 else if (hour23Range.minimum >= 12) { 165 range.minimum = hour23Range.minimum - 12; 166 range.maximum = hour23Range.maximum - 12; 167 } 168 169 RefPtr<DateTimeHour11FieldElement> field = adoptRef(new DateTimeHour11FieldElement(document, fieldOwner, range, step)); 170 field->initialize(); 171 return field.release(); 172 } 173 174 void DateTimeHour11FieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 175 { 176 if (!hasValue()) { 177 dateTimeFieldsState.setHour(DateTimeFieldsState::emptyValue); 178 return; 179 } 180 const int value = valueAsInteger(); 181 dateTimeFieldsState.setHour(value ? value : 12); 182 } 183 184 void DateTimeHour11FieldElement::setValueAsInteger(int value, EventBehavior eventBehavior) 185 { 186 value = Range(0, 23).clampValue(value) % 12; 187 DateTimeNumericFieldElement::setValueAsInteger(value, eventBehavior); 188 } 189 190 // ---------------------------- 191 192 DateTimeHour12FieldElement::DateTimeHour12FieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 193 : DateTimeHourFieldElementBase(document, fieldOwner, range, Range(1, 12), step) 194 { 195 } 196 197 PassRefPtr<DateTimeHour12FieldElement> DateTimeHour12FieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) 198 { 199 ASSERT(hour23Range.minimum >= 0); 200 ASSERT(hour23Range.maximum <= 23); 201 ASSERT(hour23Range.minimum <= hour23Range.maximum); 202 Range range(1, 12); 203 if (hour23Range.maximum < 12) 204 range = hour23Range; 205 else if (hour23Range.minimum >= 12) { 206 range.minimum = hour23Range.minimum - 12; 207 range.maximum = hour23Range.maximum - 12; 208 } 209 if (!range.minimum) 210 range.minimum = 12; 211 if (!range.maximum) 212 range.maximum = 12; 213 if (range.minimum > range.maximum) { 214 range.minimum = 1; 215 range.maximum = 12; 216 } 217 RefPtr<DateTimeHour12FieldElement> field = adoptRef(new DateTimeHour12FieldElement(document, fieldOwner, range, step)); 218 field->initialize(); 219 return field.release(); 220 } 221 222 void DateTimeHour12FieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 223 { 224 dateTimeFieldsState.setHour(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 225 } 226 227 void DateTimeHour12FieldElement::setValueAsInteger(int value, EventBehavior eventBehavior) 228 { 229 value = Range(0, 24).clampValue(value) % 12; 230 DateTimeNumericFieldElement::setValueAsInteger(value ? value : 12, eventBehavior); 231 } 232 233 // ---------------------------- 234 235 DateTimeHour23FieldElement::DateTimeHour23FieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 236 : DateTimeHourFieldElementBase(document, fieldOwner, range, Range(0, 23), step) 237 { 238 } 239 240 PassRefPtr<DateTimeHour23FieldElement> DateTimeHour23FieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) 241 { 242 ASSERT(hour23Range.minimum >= 0); 243 ASSERT(hour23Range.maximum <= 23); 244 ASSERT(hour23Range.minimum <= hour23Range.maximum); 245 RefPtr<DateTimeHour23FieldElement> field = adoptRef(new DateTimeHour23FieldElement(document, fieldOwner, hour23Range, step)); 246 field->initialize(); 247 return field.release(); 248 } 249 250 void DateTimeHour23FieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 251 { 252 if (!hasValue()) { 253 dateTimeFieldsState.setHour(DateTimeFieldsState::emptyValue); 254 return; 255 } 256 257 const int value = valueAsInteger(); 258 259 dateTimeFieldsState.setHour(value ? value % 12 : 12); 260 dateTimeFieldsState.setAMPM(value >= 12 ? DateTimeFieldsState::AMPMValuePM : DateTimeFieldsState::AMPMValueAM); 261 } 262 263 void DateTimeHour23FieldElement::setValueAsInteger(int value, EventBehavior eventBehavior) 264 { 265 value = Range(0, 23).clampValue(value); 266 DateTimeNumericFieldElement::setValueAsInteger(value, eventBehavior); 267 } 268 269 // ---------------------------- 270 271 DateTimeHour24FieldElement::DateTimeHour24FieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 272 : DateTimeHourFieldElementBase(document, fieldOwner, range, Range(1, 24), step) 273 { 274 } 275 276 PassRefPtr<DateTimeHour24FieldElement> DateTimeHour24FieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) 277 { 278 ASSERT(hour23Range.minimum >= 0); 279 ASSERT(hour23Range.maximum <= 23); 280 ASSERT(hour23Range.minimum <= hour23Range.maximum); 281 Range range(hour23Range.minimum ? hour23Range.minimum : 24, hour23Range.maximum ? hour23Range.maximum : 24); 282 if (range.minimum > range.maximum) { 283 range.minimum = 1; 284 range.maximum = 24; 285 } 286 287 RefPtr<DateTimeHour24FieldElement> field = adoptRef(new DateTimeHour24FieldElement(document, fieldOwner, range, step)); 288 field->initialize(); 289 return field.release(); 290 } 291 292 void DateTimeHour24FieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 293 { 294 if (!hasValue()) { 295 dateTimeFieldsState.setHour(DateTimeFieldsState::emptyValue); 296 return; 297 } 298 299 const int value = valueAsInteger(); 300 301 if (value == 24) { 302 dateTimeFieldsState.setHour(12); 303 dateTimeFieldsState.setAMPM(DateTimeFieldsState::AMPMValueAM); 304 } else { 305 dateTimeFieldsState.setHour(value == 12 ? 12 : value % 12); 306 dateTimeFieldsState.setAMPM(value >= 12 ? DateTimeFieldsState::AMPMValuePM : DateTimeFieldsState::AMPMValueAM); 307 } 308 } 309 310 void DateTimeHour24FieldElement::setValueAsInteger(int value, EventBehavior eventBehavior) 311 { 312 value = Range(0, 24).clampValue(value); 313 DateTimeNumericFieldElement::setValueAsInteger(value ? value : 24, eventBehavior); 314 } 315 316 // ---------------------------- 317 318 DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 319 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(0, 999), "---", step) 320 { 321 } 322 323 PassRefPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 324 { 325 DEFINE_STATIC_LOCAL(AtomicString, millisecondPsuedoId, ("-webkit-datetime-edit-millisecond-field", AtomicString::ConstructFromLiteral)); 326 RefPtr<DateTimeMillisecondFieldElement> field = adoptRef(new DateTimeMillisecondFieldElement(document, fieldOwner, range, step)); 327 field->initialize(millisecondPsuedoId, AXMillisecondFieldText()); 328 return field.release(); 329 } 330 331 void DateTimeMillisecondFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 332 { 333 dateTimeFieldsState.setMillisecond(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 334 } 335 336 void DateTimeMillisecondFieldElement::setValueAsDate(const DateComponents& date) 337 { 338 setValueAsInteger(date.millisecond()); 339 } 340 341 void DateTimeMillisecondFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 342 { 343 if (!dateTimeFieldsState.hasMillisecond()) { 344 setEmptyValue(); 345 return; 346 } 347 348 const unsigned value = dateTimeFieldsState.millisecond(); 349 if (value > static_cast<unsigned>(maximum())) { 350 setEmptyValue(); 351 return; 352 } 353 354 setValueAsInteger(value); 355 } 356 357 // ---------------------------- 358 359 DateTimeMinuteFieldElement::DateTimeMinuteFieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 360 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(0, 59), "--", step) 361 { 362 } 363 364 PassRefPtr<DateTimeMinuteFieldElement> DateTimeMinuteFieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 365 { 366 DEFINE_STATIC_LOCAL(AtomicString, minutePsuedoId, ("-webkit-datetime-edit-minute-field", AtomicString::ConstructFromLiteral)); 367 RefPtr<DateTimeMinuteFieldElement> field = adoptRef(new DateTimeMinuteFieldElement(document, fieldOwner, range, step)); 368 field->initialize(minutePsuedoId, AXMinuteFieldText()); 369 return field.release(); 370 } 371 372 void DateTimeMinuteFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 373 { 374 dateTimeFieldsState.setMinute(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 375 } 376 377 void DateTimeMinuteFieldElement::setValueAsDate(const DateComponents& date) 378 { 379 setValueAsInteger(date.minute()); 380 } 381 382 void DateTimeMinuteFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 383 { 384 if (!dateTimeFieldsState.hasMinute()) { 385 setEmptyValue(); 386 return; 387 } 388 389 const unsigned value = dateTimeFieldsState.minute(); 390 if (value > static_cast<unsigned>(maximum())) { 391 setEmptyValue(); 392 return; 393 } 394 395 setValueAsInteger(value); 396 } 397 398 // ---------------------------- 399 400 DateTimeMonthFieldElement::DateTimeMonthFieldElement(Document* document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) 401 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(1, 12), placeholder) 402 { 403 } 404 405 PassRefPtr<DateTimeMonthFieldElement> DateTimeMonthFieldElement::create(Document* document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) 406 { 407 DEFINE_STATIC_LOCAL(AtomicString, monthPsuedoId, ("-webkit-datetime-edit-month-field", AtomicString::ConstructFromLiteral)); 408 RefPtr<DateTimeMonthFieldElement> field = adoptRef(new DateTimeMonthFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); 409 field->initialize(monthPsuedoId, AXMonthFieldText()); 410 return field.release(); 411 } 412 413 void DateTimeMonthFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 414 { 415 dateTimeFieldsState.setMonth(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 416 } 417 418 void DateTimeMonthFieldElement::setValueAsDate(const DateComponents& date) 419 { 420 setValueAsInteger(date.month() + 1); 421 } 422 423 void DateTimeMonthFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 424 { 425 if (!dateTimeFieldsState.hasMonth()) { 426 setEmptyValue(); 427 return; 428 } 429 430 const unsigned value = dateTimeFieldsState.month(); 431 if (range().isInRange(static_cast<int>(value))) { 432 setValueAsInteger(value); 433 return; 434 } 435 436 setEmptyValue(); 437 } 438 439 // ---------------------------- 440 441 DateTimeSecondFieldElement::DateTimeSecondFieldElement(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 442 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(0, 59), "--", step) 443 { 444 } 445 446 PassRefPtr<DateTimeSecondFieldElement> DateTimeSecondFieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& range, const Step& step) 447 { 448 DEFINE_STATIC_LOCAL(AtomicString, secondPsuedoId, ("-webkit-datetime-edit-second-field", AtomicString::ConstructFromLiteral)); 449 RefPtr<DateTimeSecondFieldElement> field = adoptRef(new DateTimeSecondFieldElement(document, fieldOwner, range, step)); 450 field->initialize(secondPsuedoId, AXSecondFieldText()); 451 return field.release(); 452 } 453 454 void DateTimeSecondFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 455 { 456 dateTimeFieldsState.setSecond(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 457 } 458 459 void DateTimeSecondFieldElement::setValueAsDate(const DateComponents& date) 460 { 461 setValueAsInteger(date.second()); 462 } 463 464 void DateTimeSecondFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 465 { 466 if (!dateTimeFieldsState.hasSecond()) { 467 setEmptyValue(); 468 return; 469 } 470 471 const unsigned value = dateTimeFieldsState.second(); 472 if (value > static_cast<unsigned>(maximum())) { 473 setEmptyValue(); 474 return; 475 } 476 477 setValueAsInteger(value); 478 } 479 480 // ---------------------------- 481 482 DateTimeSymbolicMonthFieldElement::DateTimeSymbolicMonthFieldElement(Document* document, FieldOwner& fieldOwner, const Vector<String>& labels, int minimum, int maximum) 483 : DateTimeSymbolicFieldElement(document, fieldOwner, labels, minimum, maximum) 484 { 485 } 486 487 PassRefPtr<DateTimeSymbolicMonthFieldElement> DateTimeSymbolicMonthFieldElement::create(Document* document, FieldOwner& fieldOwner, const Vector<String>& labels, int minimum, int maximum) 488 { 489 DEFINE_STATIC_LOCAL(AtomicString, monthPsuedoId, ("-webkit-datetime-edit-month-field", AtomicString::ConstructFromLiteral)); 490 RefPtr<DateTimeSymbolicMonthFieldElement> field = adoptRef(new DateTimeSymbolicMonthFieldElement(document, fieldOwner, labels, minimum, maximum)); 491 field->initialize(monthPsuedoId, AXMonthFieldText()); 492 return field.release(); 493 } 494 495 void DateTimeSymbolicMonthFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 496 { 497 if (!hasValue()) 498 dateTimeFieldsState.setMonth(DateTimeFieldsState::emptyValue); 499 ASSERT(valueAsInteger() < static_cast<int>(symbolsSize())); 500 dateTimeFieldsState.setMonth(valueAsInteger() + 1); 501 } 502 503 void DateTimeSymbolicMonthFieldElement::setValueAsDate(const DateComponents& date) 504 { 505 setValueAsInteger(date.month()); 506 } 507 508 void DateTimeSymbolicMonthFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 509 { 510 if (!dateTimeFieldsState.hasMonth()) { 511 setEmptyValue(); 512 return; 513 } 514 515 const unsigned value = dateTimeFieldsState.month() - 1; 516 if (value >= symbolsSize()) { 517 setEmptyValue(); 518 return; 519 } 520 521 setValueAsInteger(value); 522 } 523 524 // ---------------------------- 525 526 DateTimeWeekFieldElement::DateTimeWeekFieldElement(Document* document, FieldOwner& fieldOwner, const Range& range) 527 : DateTimeNumericFieldElement(document, fieldOwner, range, Range(DateComponents::minimumWeekNumber, DateComponents::maximumWeekNumber), "--") 528 { 529 } 530 531 PassRefPtr<DateTimeWeekFieldElement> DateTimeWeekFieldElement::create(Document* document, FieldOwner& fieldOwner, const Range& range) 532 { 533 DEFINE_STATIC_LOCAL(AtomicString, weekPsuedoId, ("-webkit-datetime-edit-week-field", AtomicString::ConstructFromLiteral)); 534 RefPtr<DateTimeWeekFieldElement> field = adoptRef(new DateTimeWeekFieldElement(document, fieldOwner, range)); 535 field->initialize(weekPsuedoId, AXWeekOfYearFieldText()); 536 return field.release(); 537 } 538 539 void DateTimeWeekFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 540 { 541 dateTimeFieldsState.setWeekOfYear(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 542 } 543 544 void DateTimeWeekFieldElement::setValueAsDate(const DateComponents& date) 545 { 546 setValueAsInteger(date.week()); 547 } 548 549 void DateTimeWeekFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 550 { 551 if (!dateTimeFieldsState.hasWeekOfYear()) { 552 setEmptyValue(); 553 return; 554 } 555 556 const unsigned value = dateTimeFieldsState.weekOfYear(); 557 if (range().isInRange(static_cast<int>(value))) { 558 setValueAsInteger(value); 559 return; 560 } 561 562 setEmptyValue(); 563 } 564 565 // ---------------------------- 566 567 DateTimeYearFieldElement::DateTimeYearFieldElement(Document* document, FieldOwner& fieldOwner, const DateTimeYearFieldElement::Parameters& parameters) 568 : DateTimeNumericFieldElement(document, fieldOwner, Range(parameters.minimumYear, parameters.maximumYear), Range(DateComponents::minimumYear(), DateComponents::maximumYear()), parameters.placeholder.isEmpty() ? "----" : parameters.placeholder) 569 , m_minIsSpecified(parameters.minIsSpecified) 570 , m_maxIsSpecified(parameters.maxIsSpecified) 571 { 572 ASSERT(parameters.minimumYear >= DateComponents::minimumYear()); 573 ASSERT(parameters.maximumYear <= DateComponents::maximumYear()); 574 } 575 576 PassRefPtr<DateTimeYearFieldElement> DateTimeYearFieldElement::create(Document* document, FieldOwner& fieldOwner, const DateTimeYearFieldElement::Parameters& parameters) 577 { 578 DEFINE_STATIC_LOCAL(AtomicString, yearPsuedoId, ("-webkit-datetime-edit-year-field", AtomicString::ConstructFromLiteral)); 579 RefPtr<DateTimeYearFieldElement> field = adoptRef(new DateTimeYearFieldElement(document, fieldOwner, parameters)); 580 field->initialize(yearPsuedoId, AXYearFieldText()); 581 return field.release(); 582 } 583 584 static int currentFullYear() 585 { 586 double current = currentTimeMS(); 587 double utcOffset = calculateUTCOffset(); 588 double dstOffset = calculateDSTOffset(current, utcOffset); 589 int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); 590 current += offset * msPerMinute; 591 592 DateComponents date; 593 date.setMillisecondsSinceEpochForMonth(current); 594 return date.fullYear(); 595 } 596 597 int DateTimeYearFieldElement::defaultValueForStepDown() const 598 { 599 return m_maxIsSpecified ? DateTimeNumericFieldElement::defaultValueForStepDown() : currentFullYear(); 600 } 601 602 int DateTimeYearFieldElement::defaultValueForStepUp() const 603 { 604 return m_minIsSpecified ? DateTimeNumericFieldElement::defaultValueForStepUp() : currentFullYear(); 605 } 606 607 void DateTimeYearFieldElement::populateDateTimeFieldsState(DateTimeFieldsState& dateTimeFieldsState) 608 { 609 dateTimeFieldsState.setYear(hasValue() ? valueAsInteger() : DateTimeFieldsState::emptyValue); 610 } 611 612 void DateTimeYearFieldElement::setValueAsDate(const DateComponents& date) 613 { 614 setValueAsInteger(date.fullYear()); 615 } 616 617 void DateTimeYearFieldElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) 618 { 619 if (!dateTimeFieldsState.hasYear()) { 620 setEmptyValue(); 621 return; 622 } 623 624 const unsigned value = dateTimeFieldsState.year(); 625 if (range().isInRange(static_cast<int>(value))) { 626 setValueAsInteger(value); 627 return; 628 } 629 630 setEmptyValue(); 631 } 632 633 } // namespace WebCore 634 635 #endif 636