Home | History | Annotate | Download | only in shadow
      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