Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2010 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
     33 #include "core/html/BaseMultipleFieldsDateAndTimeInputType.h"
     34 
     35 #include "CSSValueKeywords.h"
     36 #include "RuntimeEnabledFeatures.h"
     37 #include "core/dom/KeyboardEvent.h"
     38 #include "core/dom/shadow/ShadowRoot.h"
     39 #include "core/html/DateTimeFieldsState.h"
     40 #include "core/html/FormController.h"
     41 #include "core/html/HTMLDataListElement.h"
     42 #include "core/html/HTMLInputElement.h"
     43 #include "core/html/HTMLOptionElement.h"
     44 #include "core/html/shadow/PickerIndicatorElement.h"
     45 #include "core/html/shadow/ShadowElementNames.h"
     46 #include "core/page/FocusController.h"
     47 #include "core/page/Page.h"
     48 #include "core/platform/DateComponents.h"
     49 #include "core/platform/LocalizedStrings.h"
     50 #include "core/platform/text/DateTimeFormat.h"
     51 #include "core/platform/text/PlatformLocale.h"
     52 #include "core/rendering/RenderTheme.h"
     53 #include "wtf/DateMath.h"
     54 
     55 namespace WebCore {
     56 
     57 class DateTimeFormatValidator : public DateTimeFormat::TokenHandler {
     58 public:
     59     DateTimeFormatValidator()
     60         : m_hasYear(false)
     61         , m_hasMonth(false)
     62         , m_hasWeek(false)
     63         , m_hasDay(false)
     64         , m_hasAMPM(false)
     65         , m_hasHour(false)
     66         , m_hasMinute(false)
     67         , m_hasSecond(false) { }
     68 
     69     virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
     70     virtual void visitLiteral(const String&) OVERRIDE FINAL { }
     71 
     72     bool validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType&);
     73 
     74 private:
     75     bool m_hasYear;
     76     bool m_hasMonth;
     77     bool m_hasWeek;
     78     bool m_hasDay;
     79     bool m_hasAMPM;
     80     bool m_hasHour;
     81     bool m_hasMinute;
     82     bool m_hasSecond;
     83 };
     84 
     85 void DateTimeFormatValidator::visitField(DateTimeFormat::FieldType fieldType, int)
     86 {
     87     switch (fieldType) {
     88     case DateTimeFormat::FieldTypeYear:
     89         m_hasYear = true;
     90         break;
     91     case DateTimeFormat::FieldTypeMonth: // Fallthrough.
     92     case DateTimeFormat::FieldTypeMonthStandAlone:
     93         m_hasMonth = true;
     94         break;
     95     case DateTimeFormat::FieldTypeWeekOfYear:
     96         m_hasWeek = true;
     97         break;
     98     case DateTimeFormat::FieldTypeDayOfMonth:
     99         m_hasDay = true;
    100         break;
    101     case DateTimeFormat::FieldTypePeriod:
    102         m_hasAMPM = true;
    103         break;
    104     case DateTimeFormat::FieldTypeHour11: // Fallthrough.
    105     case DateTimeFormat::FieldTypeHour12:
    106         m_hasHour = true;
    107         break;
    108     case DateTimeFormat::FieldTypeHour23: // Fallthrough.
    109     case DateTimeFormat::FieldTypeHour24:
    110         m_hasHour = true;
    111         m_hasAMPM = true;
    112         break;
    113     case DateTimeFormat::FieldTypeMinute:
    114         m_hasMinute = true;
    115         break;
    116     case DateTimeFormat::FieldTypeSecond:
    117         m_hasSecond = true;
    118         break;
    119     default:
    120         break;
    121     }
    122 }
    123 
    124 bool DateTimeFormatValidator::validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType& inputType)
    125 {
    126     if (!DateTimeFormat::parse(format, *this))
    127         return false;
    128     return inputType.isValidFormat(m_hasYear, m_hasMonth, m_hasWeek, m_hasDay, m_hasAMPM, m_hasHour, m_hasMinute, m_hasSecond);
    129 }
    130 
    131 DateTimeEditElement* BaseMultipleFieldsDateAndTimeInputType::dateTimeEditElement() const
    132 {
    133     return toDateTimeEditElement(element()->uaShadowElementById(ShadowElementNames::dateTimeEdit()));
    134 }
    135 
    136 SpinButtonElement* BaseMultipleFieldsDateAndTimeInputType::spinButtonElement() const
    137 {
    138     return toSpinButtonElement(element()->uaShadowElementById(ShadowElementNames::spinButton()));
    139 }
    140 
    141 ClearButtonElement* BaseMultipleFieldsDateAndTimeInputType::clearButtonElement() const
    142 {
    143     return toClearButtonElement(element()->uaShadowElementById(ShadowElementNames::clearButton()));
    144 }
    145 
    146 PickerIndicatorElement* BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorElement() const
    147 {
    148     return toPickerIndicatorElement(element()->uaShadowElementById(ShadowElementNames::pickerIndicator()));
    149 }
    150 
    151 inline bool BaseMultipleFieldsDateAndTimeInputType::containsFocusedShadowElement() const
    152 {
    153     return element()->userAgentShadowRoot()->contains(element()->document()->focusedElement());
    154 }
    155 
    156 void BaseMultipleFieldsDateAndTimeInputType::didBlurFromControl()
    157 {
    158     // We don't need to call blur(). This function is called when control
    159     // lost focus.
    160 
    161     if (containsFocusedShadowElement())
    162         return;
    163     RefPtr<HTMLInputElement> protector(element());
    164     // Remove focus ring by CSS "focus" pseudo class.
    165     element()->setFocus(false);
    166 }
    167 
    168 void BaseMultipleFieldsDateAndTimeInputType::didFocusOnControl()
    169 {
    170     // We don't need to call focus(). This function is called when control
    171     // got focus.
    172 
    173     if (!containsFocusedShadowElement())
    174         return;
    175     // Add focus ring by CSS "focus" pseudo class.
    176     // FIXME: Setting the focus flag to non-focused element is too tricky.
    177     element()->setFocus(true);
    178 }
    179 
    180 void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged()
    181 {
    182     RefPtr<HTMLInputElement> input(element());
    183     String oldValue = input->value();
    184     String newValue = sanitizeValue(dateTimeEditElement()->value());
    185     // Even if oldValue is null and newValue is "", we should assume they are same.
    186     if ((oldValue.isEmpty() && newValue.isEmpty()) || oldValue == newValue)
    187         input->setNeedsValidityCheck();
    188     else {
    189         input->setValueInternal(newValue, DispatchNoEvent);
    190         input->setNeedsStyleRecalc();
    191         input->dispatchFormControlInputEvent();
    192         input->dispatchFormControlChangeEvent();
    193     }
    194     input->notifyFormStateChanged();
    195     input->updateClearButtonVisibility();
    196 }
    197 
    198 bool BaseMultipleFieldsDateAndTimeInputType::hasCustomFocusLogic() const
    199 {
    200     return false;
    201 }
    202 
    203 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerDisabled() const
    204 {
    205     return element()->isDisabledFormControl();
    206 }
    207 
    208 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerReadOnly() const
    209 {
    210     return element()->isReadOnly();
    211 }
    212 
    213 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectSpinButtonOwner()
    214 {
    215     if (DateTimeEditElement* edit = dateTimeEditElement())
    216         edit->focusIfNoFocus();
    217 }
    218 
    219 bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToMouseEvents()
    220 {
    221     return !element()->isDisabledOrReadOnly();
    222 }
    223 
    224 bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToWheelEvents()
    225 {
    226     if (!shouldSpinButtonRespondToMouseEvents())
    227         return false;
    228     if (DateTimeEditElement* edit = dateTimeEditElement())
    229         return edit->hasFocusedField();
    230     return false;
    231 }
    232 
    233 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepDown()
    234 {
    235     if (DateTimeEditElement* edit = dateTimeEditElement())
    236         edit->stepDown();
    237 }
    238 
    239 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepUp()
    240 {
    241     if (DateTimeEditElement* edit = dateTimeEditElement())
    242         edit->stepUp();
    243 }
    244 
    245 bool BaseMultipleFieldsDateAndTimeInputType::isPickerIndicatorOwnerDisabledOrReadOnly() const
    246 {
    247     return element()->isDisabledOrReadOnly();
    248 }
    249 
    250 void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(const String& value)
    251 {
    252     if (element()->isValidValue(value)) {
    253         element()->setValue(value, DispatchInputAndChangeEvent);
    254         return;
    255     }
    256 
    257     DateTimeEditElement* edit = this->dateTimeEditElement();
    258     if (!edit)
    259         return;
    260     DateComponents date;
    261     unsigned end;
    262     if (date.parseDate(value, 0, end) && end == value.length())
    263         edit->setOnlyYearMonthDay(date);
    264 }
    265 
    266 bool BaseMultipleFieldsDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
    267 {
    268     return element()->setupDateTimeChooserParameters(parameters);
    269 }
    270 
    271 BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement* element)
    272     : BaseDateAndTimeInputType(element)
    273     , m_isDestroyingShadowSubtree(false)
    274     , m_pickerIndicatorIsVisible(false)
    275     , m_pickerIndicatorIsAlwaysVisible(false)
    276     , m_didCreateShadowElements(false)
    277 {
    278 }
    279 
    280 BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType()
    281 {
    282     if (!m_didCreateShadowElements)
    283         return;
    284     if (SpinButtonElement* element = spinButtonElement())
    285         element->removeSpinButtonOwner();
    286     if (ClearButtonElement* element = clearButtonElement())
    287         element->removeClearButtonOwner();
    288     if (DateTimeEditElement* element = dateTimeEditElement())
    289         element->removeEditControlOwner();
    290     if (PickerIndicatorElement* element = pickerIndicatorElement())
    291         element->removePickerIndicatorOwner();
    292 }
    293 
    294 String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
    295 {
    296     return validationMessageBadInputForDateTimeText();
    297 }
    298 
    299 void BaseMultipleFieldsDateAndTimeInputType::blur()
    300 {
    301     if (DateTimeEditElement* edit = dateTimeEditElement())
    302         edit->blurByOwner();
    303 }
    304 
    305 PassRefPtr<RenderStyle> BaseMultipleFieldsDateAndTimeInputType::customStyleForRenderer(PassRefPtr<RenderStyle> originalStyle)
    306 {
    307     EDisplay originalDisplay = originalStyle->display();
    308     EDisplay newDisplay = originalDisplay;
    309     if (originalDisplay == INLINE || originalDisplay == INLINE_BLOCK)
    310         newDisplay = INLINE_FLEX;
    311     else if (originalDisplay == BLOCK)
    312         newDisplay = FLEX;
    313     TextDirection contentDirection = element()->locale().isRTL() ? RTL : LTR;
    314     if (originalStyle->direction() == contentDirection && originalDisplay == newDisplay)
    315         return originalStyle;
    316 
    317     RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
    318     style->setDirection(contentDirection);
    319     style->setDisplay(newDisplay);
    320     return style.release();
    321 }
    322 
    323 void BaseMultipleFieldsDateAndTimeInputType::createShadowSubtree()
    324 {
    325     ASSERT(element()->shadow());
    326 
    327     // Element must not have a renderer here, because if it did
    328     // DateTimeEditElement::customStyleForRenderer() is called in appendChild()
    329     // before the field wrapper element is created.
    330     // FIXME: This code should not depend on such craziness.
    331     ASSERT(!element()->renderer());
    332 
    333     Document* document = element()->document();
    334     ContainerNode* container = element()->userAgentShadowRoot();
    335 
    336     container->appendChild(DateTimeEditElement::create(document, *this));
    337     updateInnerTextValue();
    338     container->appendChild(ClearButtonElement::create(document, *this));
    339     container->appendChild(SpinButtonElement::create(document, *this));
    340 
    341     bool shouldAddPickerIndicator = false;
    342     if (InputType::themeSupportsDataListUI(this))
    343         shouldAddPickerIndicator = true;
    344     RefPtr<RenderTheme> theme = document->page() ? document->page()->theme() : RenderTheme::defaultTheme();
    345     if (theme->supportsCalendarPicker(formControlType())) {
    346         shouldAddPickerIndicator = true;
    347         m_pickerIndicatorIsAlwaysVisible = true;
    348     }
    349     if (shouldAddPickerIndicator) {
    350         container->appendChild(PickerIndicatorElement::create(document, *this));
    351         m_pickerIndicatorIsVisible = true;
    352         updatePickerIndicatorVisibility();
    353     }
    354     m_didCreateShadowElements = true;
    355 }
    356 
    357 void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree()
    358 {
    359     ASSERT(!m_isDestroyingShadowSubtree);
    360     m_isDestroyingShadowSubtree = true;
    361     if (SpinButtonElement* element = spinButtonElement())
    362         element->removeSpinButtonOwner();
    363     if (ClearButtonElement* element = clearButtonElement())
    364         element->removeClearButtonOwner();
    365     if (DateTimeEditElement* element = dateTimeEditElement())
    366         element->removeEditControlOwner();
    367     if (PickerIndicatorElement* element = pickerIndicatorElement())
    368         element->removePickerIndicatorOwner();
    369 
    370     // If a field element has focus, set focus back to the <input> itself before
    371     // deleting the field. This prevents unnecessary focusout/blur events.
    372     if (containsFocusedShadowElement())
    373         element()->focus();
    374 
    375     BaseDateAndTimeInputType::destroyShadowSubtree();
    376     m_isDestroyingShadowSubtree = false;
    377 }
    378 
    379 void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
    380 {
    381     DateTimeEditElement* edit = dateTimeEditElement();
    382     if (!edit || m_isDestroyingShadowSubtree)
    383         return;
    384     if (direction == FocusDirectionBackward) {
    385         if (element()->document()->page())
    386             element()->document()->page()->focusController().advanceFocus(direction);
    387     } else if (direction == FocusDirectionNone || direction == FocusDirectionMouse || direction == FocusDirectionPage) {
    388         edit->focusByOwner(oldFocusedElement);
    389     } else
    390         edit->focusByOwner();
    391 }
    392 
    393 void BaseMultipleFieldsDateAndTimeInputType::forwardEvent(Event* event)
    394 {
    395     if (SpinButtonElement* element = spinButtonElement()) {
    396         element->forwardEvent(event);
    397         if (event->defaultHandled())
    398             return;
    399     }
    400 
    401     if (DateTimeEditElement* edit = dateTimeEditElement())
    402         edit->defaultEventHandler(event);
    403 }
    404 
    405 void BaseMultipleFieldsDateAndTimeInputType::disabledAttributeChanged()
    406 {
    407     spinButtonElement()->releaseCapture();
    408     clearButtonElement()->releaseCapture();
    409     if (DateTimeEditElement* edit = dateTimeEditElement())
    410         edit->disabledStateChanged();
    411 }
    412 
    413 void BaseMultipleFieldsDateAndTimeInputType::requiredAttributeChanged()
    414 {
    415     clearButtonElement()->releaseCapture();
    416     updateClearButtonVisibility();
    417 }
    418 
    419 void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
    420 {
    421     Document* document = element()->document();
    422     RefPtr<RenderTheme> theme = document->page() ? document->page()->theme() : RenderTheme::defaultTheme();
    423     if (m_pickerIndicatorIsVisible
    424         && ((event->keyIdentifier() == "Down" && event->getModifierState("Alt")) || (theme->shouldOpenPickerWithF4Key() && event->keyIdentifier() == "F4"))) {
    425         if (PickerIndicatorElement* element = pickerIndicatorElement())
    426             element->openPopup();
    427         event->setDefaultHandled();
    428     } else
    429         forwardEvent(event);
    430 }
    431 
    432 bool BaseMultipleFieldsDateAndTimeInputType::hasBadInput() const
    433 {
    434     DateTimeEditElement* edit = dateTimeEditElement();
    435     return element()->value().isEmpty() && edit && edit->anyEditableFieldsHaveValues();
    436 }
    437 
    438 AtomicString BaseMultipleFieldsDateAndTimeInputType::localeIdentifier() const
    439 {
    440     return element()->computeInheritedLanguage();
    441 }
    442 
    443 void BaseMultipleFieldsDateAndTimeInputType::minOrMaxAttributeChanged()
    444 {
    445     updateInnerTextValue();
    446 }
    447 
    448 void BaseMultipleFieldsDateAndTimeInputType::readonlyAttributeChanged()
    449 {
    450     spinButtonElement()->releaseCapture();
    451     clearButtonElement()->releaseCapture();
    452     if (DateTimeEditElement* edit = dateTimeEditElement())
    453         edit->readOnlyStateChanged();
    454 }
    455 
    456 void BaseMultipleFieldsDateAndTimeInputType::restoreFormControlState(const FormControlState& state)
    457 {
    458     DateTimeEditElement* edit = dateTimeEditElement();
    459     if (!edit)
    460         return;
    461     DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state);
    462     edit->setValueAsDateTimeFieldsState(dateTimeFieldsState);
    463     element()->setValueInternal(sanitizeValue(edit->value()), DispatchNoEvent);
    464     updateClearButtonVisibility();
    465 }
    466 
    467 FormControlState BaseMultipleFieldsDateAndTimeInputType::saveFormControlState() const
    468 {
    469     if (DateTimeEditElement* edit = dateTimeEditElement())
    470         return edit->valueAsDateTimeFieldsState().saveFormControlState();
    471     return FormControlState();
    472 }
    473 
    474 void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
    475 {
    476     InputType::setValue(sanitizedValue, valueChanged, eventBehavior);
    477     DateTimeEditElement* edit = dateTimeEditElement();
    478     if (valueChanged || (sanitizedValue.isEmpty() && edit && edit->anyEditableFieldsHaveValues())) {
    479         updateInnerTextValue();
    480         element()->setNeedsValidityCheck();
    481     }
    482 }
    483 
    484 bool BaseMultipleFieldsDateAndTimeInputType::shouldUseInputMethod() const
    485 {
    486     return false;
    487 }
    488 
    489 void BaseMultipleFieldsDateAndTimeInputType::stepAttributeChanged()
    490 {
    491     updateInnerTextValue();
    492 }
    493 
    494 void BaseMultipleFieldsDateAndTimeInputType::updateInnerTextValue()
    495 {
    496     DateTimeEditElement* edit = dateTimeEditElement();
    497     if (!edit)
    498         return;
    499 
    500     DateTimeEditElement::LayoutParameters layoutParameters(element()->locale(), createStepRange(AnyIsDefaultStep));
    501 
    502     DateComponents date;
    503     const bool hasValue = parseToDateComponents(element()->value(), &date);
    504     if (!hasValue)
    505         setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);
    506 
    507     setupLayoutParameters(layoutParameters, date);
    508 
    509     const AtomicString pattern = edit->fastGetAttribute(HTMLNames::patternAttr);
    510     if (!pattern.isEmpty())
    511         layoutParameters.dateTimeFormat = pattern;
    512 
    513     if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
    514         layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;
    515 
    516     if (hasValue)
    517         edit->setValueAsDate(layoutParameters, date);
    518     else
    519         edit->setEmptyValue(layoutParameters, date);
    520     updateClearButtonVisibility();
    521 }
    522 
    523 void BaseMultipleFieldsDateAndTimeInputType::valueAttributeChanged()
    524 {
    525     if (!element()->hasDirtyValue())
    526         updateInnerTextValue();
    527 }
    528 
    529 void BaseMultipleFieldsDateAndTimeInputType::listAttributeTargetChanged()
    530 {
    531     updatePickerIndicatorVisibility();
    532 }
    533 
    534 void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility()
    535 {
    536     if (m_pickerIndicatorIsAlwaysVisible) {
    537         showPickerIndicator();
    538         return;
    539     }
    540     if (RuntimeEnabledFeatures::dataListElementEnabled()) {
    541         if (HTMLDataListElement* dataList = element()->dataList()) {
    542             RefPtr<HTMLCollection> options = dataList->options();
    543             for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) {
    544                 if (element()->isValidValue(option->value())) {
    545                     showPickerIndicator();
    546                     return;
    547                 }
    548             }
    549         }
    550         hidePickerIndicator();
    551     }
    552 }
    553 
    554 void BaseMultipleFieldsDateAndTimeInputType::hidePickerIndicator()
    555 {
    556     if (!m_pickerIndicatorIsVisible)
    557         return;
    558     m_pickerIndicatorIsVisible = false;
    559     ASSERT(pickerIndicatorElement());
    560     pickerIndicatorElement()->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
    561 }
    562 
    563 void BaseMultipleFieldsDateAndTimeInputType::showPickerIndicator()
    564 {
    565     if (m_pickerIndicatorIsVisible)
    566         return;
    567     m_pickerIndicatorIsVisible = true;
    568     ASSERT(pickerIndicatorElement());
    569     pickerIndicatorElement()->removeInlineStyleProperty(CSSPropertyDisplay);
    570 }
    571 
    572 bool BaseMultipleFieldsDateAndTimeInputType::shouldHaveSecondField(const DateComponents& date) const
    573 {
    574     StepRange stepRange = createStepRange(AnyIsDefaultStep);
    575     return date.second() || date.millisecond()
    576         || !stepRange.minimum().remainder(static_cast<int>(msPerMinute)).isZero()
    577         || !stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
    578 }
    579 
    580 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectClearButtonOwner()
    581 {
    582     element()->focus();
    583 }
    584 
    585 bool BaseMultipleFieldsDateAndTimeInputType::shouldClearButtonRespondToMouseEvents()
    586 {
    587     return !element()->isDisabledOrReadOnly() && !element()->isRequired();
    588 }
    589 
    590 void BaseMultipleFieldsDateAndTimeInputType::clearValue()
    591 {
    592     RefPtr<HTMLInputElement> input(element());
    593     input->setValue("", DispatchInputAndChangeEvent);
    594     input->updateClearButtonVisibility();
    595 }
    596 
    597 void BaseMultipleFieldsDateAndTimeInputType::updateClearButtonVisibility()
    598 {
    599     ClearButtonElement* clearButton = clearButtonElement();
    600     if (!clearButton)
    601         return;
    602 
    603     if (element()->isRequired() || !dateTimeEditElement()->anyEditableFieldsHaveValues())
    604         clearButton->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden);
    605     else
    606         clearButton->removeInlineStyleProperty(CSSPropertyVisibility);
    607 }
    608 
    609 } // namespace WebCore
    610 
    611 #endif
    612