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/DateTimeEditElement.h"
     29 
     30 #include "HTMLNames.h"
     31 #include "bindings/v8/ExceptionStatePlaceholder.h"
     32 #include "core/dom/Text.h"
     33 #include "core/events/MouseEvent.h"
     34 #include "core/html/forms/DateTimeFieldsState.h"
     35 #include "core/html/shadow/DateTimeFieldElements.h"
     36 #include "core/html/shadow/ShadowElementNames.h"
     37 #include "core/rendering/style/RenderStyle.h"
     38 #include "core/rendering/style/StyleInheritedData.h"
     39 #include "platform/fonts/FontCache.h"
     40 #include "platform/text/DateTimeFormat.h"
     41 #include "platform/text/PlatformLocale.h"
     42 #include "wtf/DateMath.h"
     43 
     44 namespace WebCore {
     45 
     46 using namespace HTMLNames;
     47 using namespace WTF::Unicode;
     48 
     49 class DateTimeEditBuilder : private DateTimeFormat::TokenHandler {
     50     WTF_MAKE_NONCOPYABLE(DateTimeEditBuilder);
     51 
     52 public:
     53     // The argument objects must be alive until this object dies.
     54     DateTimeEditBuilder(DateTimeEditElement&, const DateTimeEditElement::LayoutParameters&, const DateComponents&);
     55 
     56     bool build(const String&);
     57 
     58 private:
     59     bool needMillisecondField() const;
     60     bool shouldAMPMFieldDisabled() const;
     61     bool shouldDayOfMonthFieldDisabled() const;
     62     bool shouldHourFieldDisabled() const;
     63     bool shouldMillisecondFieldDisabled() const;
     64     bool shouldMinuteFieldDisabled() const;
     65     bool shouldSecondFieldDisabled() const;
     66     bool shouldYearFieldDisabled() const;
     67     inline const StepRange& stepRange() const { return m_parameters.stepRange; }
     68     DateTimeNumericFieldElement::Step createStep(double msPerFieldUnit, double msPerFieldSize) const;
     69 
     70     // DateTimeFormat::TokenHandler functions.
     71     virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
     72     virtual void visitLiteral(const String&) OVERRIDE FINAL;
     73 
     74     DateTimeEditElement& m_editElement;
     75     const DateComponents m_dateValue;
     76     const DateTimeEditElement::LayoutParameters& m_parameters;
     77     DateTimeNumericFieldElement::Range m_dayRange;
     78     DateTimeNumericFieldElement::Range m_hour23Range;
     79     DateTimeNumericFieldElement::Range m_minuteRange;
     80     DateTimeNumericFieldElement::Range m_secondRange;
     81     DateTimeNumericFieldElement::Range m_millisecondRange;
     82 };
     83 
     84 DateTimeEditBuilder::DateTimeEditBuilder(DateTimeEditElement& elemnt, const DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& dateValue)
     85     : m_editElement(elemnt)
     86     , m_dateValue(dateValue)
     87     , m_parameters(layoutParameters)
     88     , m_dayRange(1, 31)
     89     , m_hour23Range(0, 23)
     90     , m_minuteRange(0, 59)
     91     , m_secondRange(0, 59)
     92     , m_millisecondRange(0, 999)
     93 {
     94     if (m_dateValue.type() == DateComponents::Date || m_dateValue.type() == DateComponents::DateTimeLocal) {
     95         if (m_parameters.minimum.type() != DateComponents::Invalid
     96             && m_parameters.maximum.type() != DateComponents::Invalid
     97             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
     98             && m_parameters.minimum.month() == m_parameters.maximum.month()
     99             && m_parameters.minimum.monthDay() <= m_parameters.maximum.monthDay()) {
    100             m_dayRange.minimum = m_parameters.minimum.monthDay();
    101             m_dayRange.maximum = m_parameters.maximum.monthDay();
    102         }
    103     }
    104 
    105     if (m_dateValue.type() == DateComponents::Time || m_dayRange.isSingleton()) {
    106         if (m_parameters.minimum.type() != DateComponents::Invalid
    107             && m_parameters.maximum.type() != DateComponents::Invalid
    108             && m_parameters.minimum.hour() <= m_parameters.maximum.hour()) {
    109             m_hour23Range.minimum = m_parameters.minimum.hour();
    110             m_hour23Range.maximum = m_parameters.maximum.hour();
    111         }
    112     }
    113 
    114     if (m_hour23Range.isSingleton() && m_parameters.minimum.minute() <= m_parameters.maximum.minute()) {
    115         m_minuteRange.minimum = m_parameters.minimum.minute();
    116         m_minuteRange.maximum = m_parameters.maximum.minute();
    117     }
    118     if (m_minuteRange.isSingleton() && m_parameters.minimum.second() <= m_parameters.maximum.second()) {
    119         m_secondRange.minimum = m_parameters.minimum.second();
    120         m_secondRange.maximum = m_parameters.maximum.second();
    121     }
    122     if (m_secondRange.isSingleton() && m_parameters.minimum.millisecond() <= m_parameters.maximum.millisecond()) {
    123         m_millisecondRange.minimum = m_parameters.minimum.millisecond();
    124         m_millisecondRange.maximum = m_parameters.maximum.millisecond();
    125     }
    126 }
    127 
    128 bool DateTimeEditBuilder::build(const String& formatString)
    129 {
    130     m_editElement.resetFields();
    131     return DateTimeFormat::parse(formatString, *this);
    132 }
    133 
    134 bool DateTimeEditBuilder::needMillisecondField() const
    135 {
    136     return m_dateValue.millisecond()
    137         || !stepRange().minimum().remainder(static_cast<int>(msPerSecond)).isZero()
    138         || !stepRange().step().remainder(static_cast<int>(msPerSecond)).isZero();
    139 }
    140 
    141 void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int count)
    142 {
    143     const int countForAbbreviatedMonth = 3;
    144     const int countForFullMonth = 4;
    145     const int countForNarrowMonth = 5;
    146     Document& document = m_editElement.document();
    147 
    148     switch (fieldType) {
    149     case DateTimeFormat::FieldTypeDayOfMonth: {
    150         RefPtr<DateTimeFieldElement> field = DateTimeDayFieldElement::create(document, m_editElement, m_parameters.placeholderForDay, m_dayRange);
    151         m_editElement.addField(field);
    152         if (shouldDayOfMonthFieldDisabled()) {
    153             field->setValueAsDate(m_dateValue);
    154             field->setDisabled();
    155         }
    156         return;
    157     }
    158 
    159     case DateTimeFormat::FieldTypeHour11: {
    160         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12);
    161         RefPtr<DateTimeFieldElement> field = DateTimeHour11FieldElement::create(document, m_editElement, m_hour23Range, step);
    162         m_editElement.addField(field);
    163         if (shouldHourFieldDisabled()) {
    164             field->setValueAsDate(m_dateValue);
    165             field->setDisabled();
    166         }
    167         return;
    168     }
    169 
    170     case DateTimeFormat::FieldTypeHour12: {
    171         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12);
    172         RefPtr<DateTimeFieldElement> field = DateTimeHour12FieldElement::create(document, m_editElement, m_hour23Range, step);
    173         m_editElement.addField(field);
    174         if (shouldHourFieldDisabled()) {
    175             field->setValueAsDate(m_dateValue);
    176             field->setDisabled();
    177         }
    178         return;
    179     }
    180 
    181     case DateTimeFormat::FieldTypeHour23: {
    182         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay);
    183         RefPtr<DateTimeFieldElement> field = DateTimeHour23FieldElement::create(document, m_editElement, m_hour23Range, step);
    184         m_editElement.addField(field);
    185         if (shouldHourFieldDisabled()) {
    186             field->setValueAsDate(m_dateValue);
    187             field->setDisabled();
    188         }
    189         return;
    190     }
    191 
    192     case DateTimeFormat::FieldTypeHour24: {
    193         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay);
    194         RefPtr<DateTimeFieldElement> field = DateTimeHour24FieldElement::create(document, m_editElement, m_hour23Range, step);
    195         m_editElement.addField(field);
    196         if (shouldHourFieldDisabled()) {
    197             field->setValueAsDate(m_dateValue);
    198             field->setDisabled();
    199         }
    200         return;
    201     }
    202 
    203     case DateTimeFormat::FieldTypeMinute: {
    204         DateTimeNumericFieldElement::Step step = createStep(msPerMinute, msPerHour);
    205         RefPtr<DateTimeNumericFieldElement> field = DateTimeMinuteFieldElement::create(document, m_editElement, m_minuteRange, step);
    206         m_editElement.addField(field);
    207         if (shouldMinuteFieldDisabled()) {
    208             field->setValueAsDate(m_dateValue);
    209             field->setDisabled();
    210         }
    211         return;
    212     }
    213 
    214     case DateTimeFormat::FieldTypeMonth: // Fallthrough.
    215     case DateTimeFormat::FieldTypeMonthStandAlone: {
    216         int minMonth = 0, maxMonth = 11;
    217         if (m_parameters.minimum.type() != DateComponents::Invalid
    218             && m_parameters.maximum.type() != DateComponents::Invalid
    219             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
    220             && m_parameters.minimum.month() <= m_parameters.maximum.month()) {
    221             minMonth = m_parameters.minimum.month();
    222             maxMonth = m_parameters.maximum.month();
    223         }
    224         RefPtr<DateTimeFieldElement> field;
    225         switch (count) {
    226         case countForNarrowMonth: // Fallthrough.
    227         case countForAbbreviatedMonth:
    228             field = DateTimeSymbolicMonthFieldElement::create(document, m_editElement, fieldType == DateTimeFormat::FieldTypeMonth ? m_parameters.locale.shortMonthLabels() : m_parameters.locale.shortStandAloneMonthLabels(), minMonth, maxMonth);
    229             break;
    230         case countForFullMonth:
    231             field = DateTimeSymbolicMonthFieldElement::create(document, m_editElement, fieldType == DateTimeFormat::FieldTypeMonth ? m_parameters.locale.monthLabels() : m_parameters.locale.standAloneMonthLabels(), minMonth, maxMonth);
    232             break;
    233         default:
    234             field = DateTimeMonthFieldElement::create(document, m_editElement, m_parameters.placeholderForMonth, DateTimeNumericFieldElement::Range(minMonth + 1, maxMonth + 1));
    235             break;
    236         }
    237         m_editElement.addField(field);
    238         if (minMonth == maxMonth && minMonth == m_dateValue.month() && m_dateValue.type() != DateComponents::Month) {
    239             field->setValueAsDate(m_dateValue);
    240             field->setDisabled();
    241         }
    242         return;
    243     }
    244 
    245     case DateTimeFormat::FieldTypePeriod: {
    246         RefPtr<DateTimeFieldElement> field = DateTimeAMPMFieldElement::create(document, m_editElement, m_parameters.locale.timeAMPMLabels());
    247         m_editElement.addField(field);
    248         if (shouldAMPMFieldDisabled()) {
    249             field->setValueAsDate(m_dateValue);
    250             field->setDisabled();
    251         }
    252         return;
    253     }
    254 
    255     case DateTimeFormat::FieldTypeSecond: {
    256         DateTimeNumericFieldElement::Step step = createStep(msPerSecond, msPerMinute);
    257         RefPtr<DateTimeNumericFieldElement> field = DateTimeSecondFieldElement::create(document, m_editElement, m_secondRange, step);
    258         m_editElement.addField(field);
    259         if (shouldSecondFieldDisabled()) {
    260             field->setValueAsDate(m_dateValue);
    261             field->setDisabled();
    262         }
    263 
    264         if (needMillisecondField()) {
    265             visitLiteral(m_parameters.locale.localizedDecimalSeparator());
    266             visitField(DateTimeFormat::FieldTypeFractionalSecond, 3);
    267         }
    268         return;
    269     }
    270 
    271     case DateTimeFormat::FieldTypeFractionalSecond: {
    272         DateTimeNumericFieldElement::Step step = createStep(1, msPerSecond);
    273         RefPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement, m_millisecondRange, step);
    274         m_editElement.addField(field);
    275         if (shouldMillisecondFieldDisabled()) {
    276             field->setValueAsDate(m_dateValue);
    277             field->setDisabled();
    278         }
    279         return;
    280     }
    281 
    282     case DateTimeFormat::FieldTypeWeekOfYear: {
    283         DateTimeNumericFieldElement::Range range(DateComponents::minimumWeekNumber, DateComponents::maximumWeekNumber);
    284         if (m_parameters.minimum.type() != DateComponents::Invalid
    285             && m_parameters.maximum.type() != DateComponents::Invalid
    286             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
    287             && m_parameters.minimum.week() <= m_parameters.maximum.week()) {
    288             range.minimum = m_parameters.minimum.week();
    289             range.maximum = m_parameters.maximum.week();
    290         }
    291         m_editElement.addField(DateTimeWeekFieldElement::create(document, m_editElement, range));
    292         return;
    293     }
    294 
    295     case DateTimeFormat::FieldTypeYear: {
    296         DateTimeYearFieldElement::Parameters yearParams;
    297         if (m_parameters.minimum.type() == DateComponents::Invalid) {
    298             yearParams.minimumYear = DateComponents::minimumYear();
    299             yearParams.minIsSpecified = false;
    300         } else {
    301             yearParams.minimumYear = m_parameters.minimum.fullYear();
    302             yearParams.minIsSpecified = true;
    303         }
    304         if (m_parameters.maximum.type() == DateComponents::Invalid) {
    305             yearParams.maximumYear = DateComponents::maximumYear();
    306             yearParams.maxIsSpecified = false;
    307         } else {
    308             yearParams.maximumYear = m_parameters.maximum.fullYear();
    309             yearParams.maxIsSpecified = true;
    310         }
    311         if (yearParams.minimumYear > yearParams.maximumYear) {
    312             std::swap(yearParams.minimumYear, yearParams.maximumYear);
    313             std::swap(yearParams.minIsSpecified, yearParams.maxIsSpecified);
    314         }
    315         yearParams.placeholder = m_parameters.placeholderForYear;
    316         RefPtr<DateTimeFieldElement> field = DateTimeYearFieldElement::create(document, m_editElement, yearParams);
    317         m_editElement.addField(field);
    318         if (shouldYearFieldDisabled()) {
    319             field->setValueAsDate(m_dateValue);
    320             field->setDisabled();
    321         }
    322         return;
    323     }
    324 
    325     default:
    326         return;
    327     }
    328 }
    329 
    330 bool DateTimeEditBuilder::shouldAMPMFieldDisabled() const
    331 {
    332     return shouldHourFieldDisabled()
    333         || (m_hour23Range.minimum < 12 && m_hour23Range.maximum < 12 && m_dateValue.hour() < 12)
    334         || (m_hour23Range.minimum >= 12 && m_hour23Range.maximum >= 12 && m_dateValue.hour() >= 12);
    335 }
    336 
    337 bool DateTimeEditBuilder::shouldDayOfMonthFieldDisabled() const
    338 {
    339     return m_dayRange.isSingleton() && m_dayRange.minimum == m_dateValue.monthDay() && m_dateValue.type() != DateComponents::Date;
    340 }
    341 
    342 bool DateTimeEditBuilder::shouldHourFieldDisabled() const
    343 {
    344     if (m_hour23Range.isSingleton() && m_hour23Range.minimum == m_dateValue.hour()
    345         && !(shouldMinuteFieldDisabled() && shouldSecondFieldDisabled() && shouldMillisecondFieldDisabled()))
    346         return true;
    347 
    348     if (m_dateValue.type() == DateComponents::Time)
    349         return false;
    350     ASSERT(m_dateValue.type() == DateComponents::DateTimeLocal);
    351 
    352     if (shouldDayOfMonthFieldDisabled()) {
    353         ASSERT(m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear());
    354         ASSERT(m_parameters.minimum.month() == m_parameters.maximum.month());
    355         return false;
    356     }
    357 
    358     const Decimal decimalMsPerDay(static_cast<int>(msPerDay));
    359     Decimal hourPartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerDay) / static_cast<int>(msPerHour)).floor();
    360     return hourPartOfMinimum == m_dateValue.hour() && stepRange().step().remainder(decimalMsPerDay).isZero();
    361 }
    362 
    363 bool DateTimeEditBuilder::shouldMillisecondFieldDisabled() const
    364 {
    365     if (m_millisecondRange.isSingleton() && m_millisecondRange.minimum == m_dateValue.millisecond())
    366         return true;
    367 
    368     const Decimal decimalMsPerSecond(static_cast<int>(msPerSecond));
    369     return stepRange().minimum().abs().remainder(decimalMsPerSecond) == m_dateValue.millisecond() && stepRange().step().remainder(decimalMsPerSecond).isZero();
    370 }
    371 
    372 bool DateTimeEditBuilder::shouldMinuteFieldDisabled() const
    373 {
    374     if (m_minuteRange.isSingleton() && m_minuteRange.minimum == m_dateValue.minute())
    375         return true;
    376 
    377     const Decimal decimalMsPerHour(static_cast<int>(msPerHour));
    378     Decimal minutePartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerHour) / static_cast<int>(msPerMinute)).floor();
    379     return minutePartOfMinimum == m_dateValue.minute() && stepRange().step().remainder(decimalMsPerHour).isZero();
    380 }
    381 
    382 bool DateTimeEditBuilder::shouldSecondFieldDisabled() const
    383 {
    384     if (m_secondRange.isSingleton() && m_secondRange.minimum == m_dateValue.second())
    385         return true;
    386 
    387     const Decimal decimalMsPerMinute(static_cast<int>(msPerMinute));
    388     Decimal secondPartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerMinute) / static_cast<int>(msPerSecond)).floor();
    389     return secondPartOfMinimum == m_dateValue.second() && stepRange().step().remainder(decimalMsPerMinute).isZero();
    390 }
    391 
    392 bool DateTimeEditBuilder::shouldYearFieldDisabled() const
    393 {
    394     return m_parameters.minimum.type() != DateComponents::Invalid
    395         && m_parameters.maximum.type() != DateComponents::Invalid
    396         && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
    397         && m_parameters.minimum.fullYear() == m_dateValue.fullYear();
    398 }
    399 
    400 void DateTimeEditBuilder::visitLiteral(const String& text)
    401 {
    402     DEFINE_STATIC_LOCAL(AtomicString, textPseudoId, ("-webkit-datetime-edit-text", AtomicString::ConstructFromLiteral));
    403     ASSERT(text.length());
    404     RefPtr<HTMLDivElement> element = HTMLDivElement::create(m_editElement.document());
    405     element->setPseudo(textPseudoId);
    406     if (m_parameters.locale.isRTL() && text.length()) {
    407         Direction dir = direction(text[0]);
    408         if (dir == SegmentSeparator || dir == WhiteSpaceNeutral || dir == OtherNeutral)
    409             element->appendChild(Text::create(m_editElement.document(), String(&rightToLeftMark, 1)));
    410     }
    411     element->appendChild(Text::create(m_editElement.document(), text));
    412     m_editElement.fieldsWrapperElement()->appendChild(element);
    413 }
    414 
    415 DateTimeNumericFieldElement::Step DateTimeEditBuilder::createStep(double msPerFieldUnit, double msPerFieldSize) const
    416 {
    417     const Decimal msPerFieldUnitDecimal(static_cast<int>(msPerFieldUnit));
    418     const Decimal msPerFieldSizeDecimal(static_cast<int>(msPerFieldSize));
    419     Decimal stepMilliseconds = stepRange().step();
    420     ASSERT(!msPerFieldUnitDecimal.isZero());
    421     ASSERT(!msPerFieldSizeDecimal.isZero());
    422     ASSERT(!stepMilliseconds.isZero());
    423 
    424     DateTimeNumericFieldElement::Step step(1, 0);
    425 
    426     if (stepMilliseconds.remainder(msPerFieldSizeDecimal).isZero())
    427         stepMilliseconds = msPerFieldSizeDecimal;
    428 
    429     if (msPerFieldSizeDecimal.remainder(stepMilliseconds).isZero() && stepMilliseconds.remainder(msPerFieldUnitDecimal).isZero()) {
    430         step.step = static_cast<int>((stepMilliseconds / msPerFieldUnitDecimal).toDouble());
    431         step.stepBase = static_cast<int>((stepRange().stepBase() / msPerFieldUnitDecimal).floor().remainder(msPerFieldSizeDecimal / msPerFieldUnitDecimal).toDouble());
    432     }
    433     return step;
    434 }
    435 
    436 // ----------------------------
    437 
    438 DateTimeEditElement::EditControlOwner::~EditControlOwner()
    439 {
    440 }
    441 
    442 DateTimeEditElement::DateTimeEditElement(Document& document, EditControlOwner& editControlOwner)
    443     : HTMLDivElement(document)
    444     , m_editControlOwner(&editControlOwner)
    445 {
    446     setHasCustomStyleCallbacks();
    447 }
    448 
    449 DateTimeEditElement::~DateTimeEditElement()
    450 {
    451     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    452         m_fields[fieldIndex]->removeEventHandler();
    453 }
    454 
    455 inline Element* DateTimeEditElement::fieldsWrapperElement() const
    456 {
    457     ASSERT(firstChild());
    458     return toElement(firstChild());
    459 }
    460 
    461 void DateTimeEditElement::addField(PassRefPtr<DateTimeFieldElement> field)
    462 {
    463     if (m_fields.size() == m_fields.capacity())
    464         return;
    465     m_fields.append(field.get());
    466     fieldsWrapperElement()->appendChild(field);
    467 }
    468 
    469 bool DateTimeEditElement::anyEditableFieldsHaveValues() const
    470 {
    471     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
    472         if (!m_fields[fieldIndex]->isDisabled() && m_fields[fieldIndex]->hasValue())
    473             return true;
    474     }
    475     return false;
    476 }
    477 
    478 void DateTimeEditElement::blurByOwner()
    479 {
    480     if (DateTimeFieldElement* field = focusedField())
    481         field->blur();
    482 }
    483 
    484 PassRefPtr<DateTimeEditElement> DateTimeEditElement::create(Document& document, EditControlOwner& editControlOwner)
    485 {
    486     RefPtr<DateTimeEditElement> container = adoptRef(new DateTimeEditElement(document, editControlOwner));
    487     container->setPseudo(AtomicString("-webkit-datetime-edit", AtomicString::ConstructFromLiteral));
    488     container->setAttribute(idAttr, ShadowElementNames::dateTimeEdit());
    489     return container.release();
    490 }
    491 
    492 PassRefPtr<RenderStyle> DateTimeEditElement::customStyleForRenderer()
    493 {
    494     // FIXME: This is a kind of layout. We might want to introduce new renderer.
    495     FontCachePurgePreventer fontCachePurgePreventer;
    496     RefPtr<RenderStyle> originalStyle = originalStyleForRenderer();
    497     RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
    498     float width = 0;
    499     for (Node* child = fieldsWrapperElement()->firstChild(); child; child = child->nextSibling()) {
    500         if (!child->isElementNode())
    501             continue;
    502         Element* childElement = toElement(child);
    503         if (childElement->isDateTimeFieldElement()) {
    504             // We need to pass the Font of this element because child elements
    505             // can't resolve inherited style at this timing.
    506             width += static_cast<DateTimeFieldElement*>(childElement)->maximumWidth(style->font());
    507         } else {
    508             // ::-webkit-datetime-edit-text case. It has no
    509             // border/padding/margin in html.css.
    510             width += style->font().width(childElement->textContent());
    511         }
    512     }
    513     style->setWidth(Length(ceilf(width), Fixed));
    514     style->setUnique();
    515     return style.release();
    516 }
    517 
    518 void DateTimeEditElement::didBlurFromField()
    519 {
    520     if (m_editControlOwner)
    521         m_editControlOwner->didBlurFromControl();
    522 }
    523 
    524 void DateTimeEditElement::didFocusOnField()
    525 {
    526     if (m_editControlOwner)
    527         m_editControlOwner->didFocusOnControl();
    528 }
    529 
    530 void DateTimeEditElement::disabledStateChanged()
    531 {
    532     updateUIState();
    533 }
    534 
    535 DateTimeFieldElement* DateTimeEditElement::fieldAt(size_t fieldIndex) const
    536 {
    537     return fieldIndex < m_fields.size() ? m_fields[fieldIndex] : 0;
    538 }
    539 
    540 size_t DateTimeEditElement::fieldIndexOf(const DateTimeFieldElement& field) const
    541 {
    542     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
    543         if (m_fields[fieldIndex] == &field)
    544             return fieldIndex;
    545     }
    546     return invalidFieldIndex;
    547 }
    548 
    549 void DateTimeEditElement::focusIfNoFocus()
    550 {
    551     if (focusedFieldIndex() != invalidFieldIndex)
    552         return;
    553     focusOnNextFocusableField(0);
    554 }
    555 
    556 void DateTimeEditElement::focusByOwner(Element* oldFocusedElement)
    557 {
    558     if (oldFocusedElement && oldFocusedElement->isDateTimeFieldElement()) {
    559         DateTimeFieldElement* oldFocusedField = static_cast<DateTimeFieldElement*>(oldFocusedElement);
    560         size_t index = fieldIndexOf(*oldFocusedField);
    561         if (index != invalidFieldIndex && oldFocusedField->isFocusable()) {
    562             oldFocusedField->focus();
    563             return;
    564         }
    565     }
    566     focusOnNextFocusableField(0);
    567 }
    568 
    569 DateTimeFieldElement* DateTimeEditElement::focusedField() const
    570 {
    571     return fieldAt(focusedFieldIndex());
    572 }
    573 
    574 size_t DateTimeEditElement::focusedFieldIndex() const
    575 {
    576     Element* const focusedFieldElement = document().focusedElement();
    577     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
    578         if (m_fields[fieldIndex] == focusedFieldElement)
    579             return fieldIndex;
    580     }
    581     return invalidFieldIndex;
    582 }
    583 
    584 void DateTimeEditElement::fieldValueChanged()
    585 {
    586     if (m_editControlOwner)
    587         m_editControlOwner->editControlValueChanged();
    588 }
    589 
    590 bool DateTimeEditElement::focusOnNextFocusableField(size_t startIndex)
    591 {
    592     for (size_t fieldIndex = startIndex; fieldIndex < m_fields.size(); ++fieldIndex) {
    593         if (m_fields[fieldIndex]->isFocusable()) {
    594             m_fields[fieldIndex]->focus();
    595             return true;
    596         }
    597     }
    598     return false;
    599 }
    600 
    601 bool DateTimeEditElement::focusOnNextField(const DateTimeFieldElement& field)
    602 {
    603     const size_t startFieldIndex = fieldIndexOf(field);
    604     if (startFieldIndex == invalidFieldIndex)
    605         return false;
    606     return focusOnNextFocusableField(startFieldIndex + 1);
    607 }
    608 
    609 bool DateTimeEditElement::focusOnPreviousField(const DateTimeFieldElement& field)
    610 {
    611     const size_t startFieldIndex = fieldIndexOf(field);
    612     if (startFieldIndex == invalidFieldIndex)
    613         return false;
    614     size_t fieldIndex = startFieldIndex;
    615     while (fieldIndex > 0) {
    616         --fieldIndex;
    617         if (m_fields[fieldIndex]->isFocusable()) {
    618             m_fields[fieldIndex]->focus();
    619             return true;
    620         }
    621     }
    622     return false;
    623 }
    624 
    625 bool DateTimeEditElement::isDateTimeEditElement() const
    626 {
    627     return true;
    628 }
    629 
    630 bool DateTimeEditElement::isDisabled() const
    631 {
    632     return m_editControlOwner && m_editControlOwner->isEditControlOwnerDisabled();
    633 }
    634 
    635 bool DateTimeEditElement::isFieldOwnerDisabled() const
    636 {
    637     return isDisabled();
    638 }
    639 
    640 bool DateTimeEditElement::isFieldOwnerReadOnly() const
    641 {
    642     return isReadOnly();
    643 }
    644 
    645 bool DateTimeEditElement::isReadOnly() const
    646 {
    647     return m_editControlOwner && m_editControlOwner->isEditControlOwnerReadOnly();
    648 }
    649 
    650 void DateTimeEditElement::layout(const LayoutParameters& layoutParameters, const DateComponents& dateValue)
    651 {
    652     DEFINE_STATIC_LOCAL(AtomicString, fieldsWrapperPseudoId, ("-webkit-datetime-edit-fields-wrapper", AtomicString::ConstructFromLiteral));
    653     if (!firstChild()) {
    654         RefPtr<HTMLDivElement> element = HTMLDivElement::create(document());
    655         element->setPseudo(fieldsWrapperPseudoId);
    656         appendChild(element.get());
    657     }
    658     Element* fieldsWrapper = fieldsWrapperElement();
    659 
    660     size_t focusedFieldIndex = this->focusedFieldIndex();
    661     DateTimeFieldElement* const focusedField = fieldAt(focusedFieldIndex);
    662     const AtomicString focusedFieldId = focusedField ? focusedField->shadowPseudoId() : nullAtom;
    663 
    664     DateTimeEditBuilder builder(*this, layoutParameters, dateValue);
    665     Node* lastChildToBeRemoved = fieldsWrapper->lastChild();
    666     if (!builder.build(layoutParameters.dateTimeFormat) || m_fields.isEmpty()) {
    667         lastChildToBeRemoved = fieldsWrapper->lastChild();
    668         builder.build(layoutParameters.fallbackDateTimeFormat);
    669     }
    670 
    671     if (focusedFieldIndex != invalidFieldIndex) {
    672         for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
    673             if (m_fields[fieldIndex]->shadowPseudoId() == focusedFieldId) {
    674                 focusedFieldIndex = fieldIndex;
    675                 break;
    676             }
    677         }
    678         if (DateTimeFieldElement* field = fieldAt(std::min(focusedFieldIndex, m_fields.size() - 1)))
    679             field->focus();
    680     }
    681 
    682     if (lastChildToBeRemoved) {
    683         for (Node* childNode = fieldsWrapper->firstChild(); childNode; childNode = fieldsWrapper->firstChild()) {
    684             fieldsWrapper->removeChild(childNode);
    685             if (childNode == lastChildToBeRemoved)
    686                 break;
    687         }
    688         setNeedsStyleRecalc();
    689     }
    690 }
    691 
    692 AtomicString DateTimeEditElement::localeIdentifier() const
    693 {
    694     return m_editControlOwner ? m_editControlOwner->localeIdentifier() : nullAtom;
    695 }
    696 
    697 void DateTimeEditElement::readOnlyStateChanged()
    698 {
    699     updateUIState();
    700 }
    701 
    702 void DateTimeEditElement::resetFields()
    703 {
    704     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    705         m_fields[fieldIndex]->removeEventHandler();
    706     m_fields.shrink(0);
    707 }
    708 
    709 void DateTimeEditElement::defaultEventHandler(Event* event)
    710 {
    711     // In case of control owner forward event to control, e.g. DOM
    712     // dispatchEvent method.
    713     if (DateTimeFieldElement* field = focusedField()) {
    714         field->defaultEventHandler(event);
    715         if (event->defaultHandled())
    716             return;
    717     }
    718 
    719     HTMLDivElement::defaultEventHandler(event);
    720 }
    721 
    722 void DateTimeEditElement::setValueAsDate(const LayoutParameters& layoutParameters, const DateComponents& date)
    723 {
    724     layout(layoutParameters, date);
    725     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    726         m_fields[fieldIndex]->setValueAsDate(date);
    727 }
    728 
    729 void DateTimeEditElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState)
    730 {
    731     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    732         m_fields[fieldIndex]->setValueAsDateTimeFieldsState(dateTimeFieldsState);
    733 }
    734 
    735 void DateTimeEditElement::setEmptyValue(const LayoutParameters& layoutParameters, const DateComponents& dateForReadOnlyField)
    736 {
    737     layout(layoutParameters, dateForReadOnlyField);
    738     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    739         m_fields[fieldIndex]->setEmptyValue(DateTimeFieldElement::DispatchNoEvent);
    740 }
    741 
    742 bool DateTimeEditElement::hasFocusedField()
    743 {
    744     return focusedFieldIndex() != invalidFieldIndex;
    745 }
    746 
    747 void DateTimeEditElement::setOnlyYearMonthDay(const DateComponents& date)
    748 {
    749     ASSERT(date.type() == DateComponents::Date);
    750 
    751     if (!m_editControlOwner)
    752         return;
    753 
    754     DateTimeFieldsState dateTimeFieldsState = valueAsDateTimeFieldsState();
    755     dateTimeFieldsState.setYear(date.fullYear());
    756     dateTimeFieldsState.setMonth(date.month() + 1);
    757     dateTimeFieldsState.setDayOfMonth(date.monthDay());
    758     setValueAsDateTimeFieldsState(dateTimeFieldsState);
    759     m_editControlOwner->editControlValueChanged();
    760 }
    761 
    762 void DateTimeEditElement::stepDown()
    763 {
    764     if (DateTimeFieldElement* const field = focusedField())
    765         field->stepDown();
    766 }
    767 
    768 void DateTimeEditElement::stepUp()
    769 {
    770     if (DateTimeFieldElement* const field = focusedField())
    771         field->stepUp();
    772 }
    773 
    774 void DateTimeEditElement::updateUIState()
    775 {
    776     if (isDisabled()) {
    777         if (DateTimeFieldElement* field = focusedField())
    778             field->blur();
    779     }
    780 }
    781 
    782 String DateTimeEditElement::value() const
    783 {
    784     if (!m_editControlOwner)
    785         return emptyString();
    786     return m_editControlOwner->formatDateTimeFieldsState(valueAsDateTimeFieldsState());
    787 }
    788 
    789 DateTimeFieldsState DateTimeEditElement::valueAsDateTimeFieldsState() const
    790 {
    791     DateTimeFieldsState dateTimeFieldsState;
    792     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
    793         m_fields[fieldIndex]->populateDateTimeFieldsState(dateTimeFieldsState);
    794     return dateTimeFieldsState;
    795 }
    796 
    797 } // namespace WebCore
    798 
    799 #endif
    800