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