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/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 blink {
     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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeAMPMFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeDayFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeHour11FieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeHour12FieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeHour23FieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeHour24FieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeMillisecondFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeMinuteFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeMonthFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeSecondFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeSymbolicMonthFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeWeekFieldElement> field = adoptRefWillBeNoop(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 PassRefPtrWillBeRawPtr<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     RefPtrWillBeRawPtr<DateTimeYearFieldElement> field = adoptRefWillBeNoop(new DateTimeYearFieldElement(document, fieldOwner, parameters));
    586     field->initialize(yearPsuedoId, queryString(WebLocalizedString::AXYearFieldText));
    587     return field.release();
    588 }
    589 
    590 static int currentFullYear()
    591 {
    592     DateComponents date;
    593     date.setMillisecondsSinceEpochForMonth(convertToLocalTime(currentTimeMS()));
    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 blink
    634 
    635 #endif
    636