Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / forms / BaseMultipleFieldsDateAndTimeInputType.cpp
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/forms/BaseMultipleFieldsDateAndTimeInputType.h"
34
35 #include "core/CSSValueKeywords.h"
36 #include "core/dom/shadow/ShadowRoot.h"
37 #include "core/events/KeyboardEvent.h"
38 #include "core/events/ScopedEventQueue.h"
39 #include "core/html/HTMLDataListElement.h"
40 #include "core/html/HTMLInputElement.h"
41 #include "core/html/HTMLOptionElement.h"
42 #include "core/html/forms/DateTimeFieldsState.h"
43 #include "core/html/forms/FormController.h"
44 #include "core/html/shadow/ShadowElementNames.h"
45 #include "core/page/FocusController.h"
46 #include "core/page/Page.h"
47 #include "core/rendering/RenderTheme.h"
48 #include "platform/DateComponents.h"
49 #include "platform/RuntimeEnabledFeatures.h"
50 #include "platform/text/DateTimeFormat.h"
51 #include "platform/text/PlatformLocale.h"
52 #include "wtf/DateMath.h"
53
54 namespace blink {
55
56 class DateTimeFormatValidator : public DateTimeFormat::TokenHandler {
57 public:
58     DateTimeFormatValidator()
59         : m_hasYear(false)
60         , m_hasMonth(false)
61         , m_hasWeek(false)
62         , m_hasDay(false)
63         , m_hasAMPM(false)
64         , m_hasHour(false)
65         , m_hasMinute(false)
66         , m_hasSecond(false) { }
67
68     virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
69     virtual void visitLiteral(const String&) OVERRIDE FINAL { }
70
71     bool validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType&);
72
73 private:
74     bool m_hasYear;
75     bool m_hasMonth;
76     bool m_hasWeek;
77     bool m_hasDay;
78     bool m_hasAMPM;
79     bool m_hasHour;
80     bool m_hasMinute;
81     bool m_hasSecond;
82 };
83
84 void DateTimeFormatValidator::visitField(DateTimeFormat::FieldType fieldType, int)
85 {
86     switch (fieldType) {
87     case DateTimeFormat::FieldTypeYear:
88         m_hasYear = true;
89         break;
90     case DateTimeFormat::FieldTypeMonth: // Fallthrough.
91     case DateTimeFormat::FieldTypeMonthStandAlone:
92         m_hasMonth = true;
93         break;
94     case DateTimeFormat::FieldTypeWeekOfYear:
95         m_hasWeek = true;
96         break;
97     case DateTimeFormat::FieldTypeDayOfMonth:
98         m_hasDay = true;
99         break;
100     case DateTimeFormat::FieldTypePeriod:
101         m_hasAMPM = true;
102         break;
103     case DateTimeFormat::FieldTypeHour11: // Fallthrough.
104     case DateTimeFormat::FieldTypeHour12:
105         m_hasHour = true;
106         break;
107     case DateTimeFormat::FieldTypeHour23: // Fallthrough.
108     case DateTimeFormat::FieldTypeHour24:
109         m_hasHour = true;
110         m_hasAMPM = true;
111         break;
112     case DateTimeFormat::FieldTypeMinute:
113         m_hasMinute = true;
114         break;
115     case DateTimeFormat::FieldTypeSecond:
116         m_hasSecond = true;
117         break;
118     default:
119         break;
120     }
121 }
122
123 bool DateTimeFormatValidator::validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType& inputType)
124 {
125     if (!DateTimeFormat::parse(format, *this))
126         return false;
127     return inputType.isValidFormat(m_hasYear, m_hasMonth, m_hasWeek, m_hasDay, m_hasAMPM, m_hasHour, m_hasMinute, m_hasSecond);
128 }
129
130 DateTimeEditElement* BaseMultipleFieldsDateAndTimeInputType::dateTimeEditElement() const
131 {
132     return toDateTimeEditElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::dateTimeEdit()));
133 }
134
135 SpinButtonElement* BaseMultipleFieldsDateAndTimeInputType::spinButtonElement() const
136 {
137     return toSpinButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::spinButton()));
138 }
139
140 ClearButtonElement* BaseMultipleFieldsDateAndTimeInputType::clearButtonElement() const
141 {
142     return toClearButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::clearButton()));
143 }
144
145 PickerIndicatorElement* BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorElement() const
146 {
147     return toPickerIndicatorElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::pickerIndicator()));
148 }
149
150 inline bool BaseMultipleFieldsDateAndTimeInputType::containsFocusedShadowElement() const
151 {
152     return element().userAgentShadowRoot()->contains(element().document().focusedElement());
153 }
154
155 void BaseMultipleFieldsDateAndTimeInputType::didBlurFromControl()
156 {
157     // We don't need to call blur(). This function is called when control
158     // lost focus.
159
160     if (containsFocusedShadowElement())
161         return;
162     EventQueueScope scope;
163     RefPtrWillBeRawPtr<HTMLInputElement> protector(element());
164     // Remove focus ring by CSS "focus" pseudo class.
165     element().setFocus(false);
166     if (SpinButtonElement *spinButton = spinButtonElement())
167         spinButton->releaseCapture();
168 }
169
170 void BaseMultipleFieldsDateAndTimeInputType::didFocusOnControl()
171 {
172     // We don't need to call focus(). This function is called when control
173     // got focus.
174
175     if (!containsFocusedShadowElement())
176         return;
177     // Add focus ring by CSS "focus" pseudo class.
178     // FIXME: Setting the focus flag to non-focused element is too tricky.
179     element().setFocus(true);
180 }
181
182 void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged()
183 {
184     RefPtrWillBeRawPtr<HTMLInputElement> input(element());
185     String oldValue = input->value();
186     String newValue = sanitizeValue(dateTimeEditElement()->value());
187     // Even if oldValue is null and newValue is "", we should assume they are same.
188     if ((oldValue.isEmpty() && newValue.isEmpty()) || oldValue == newValue) {
189         input->setNeedsValidityCheck();
190     } else {
191         input->setValueInternal(newValue, DispatchNoEvent);
192         input->setNeedsStyleRecalc(SubtreeStyleChange);
193         input->dispatchFormControlInputEvent();
194     }
195     input->notifyFormStateChanged();
196     input->updateClearButtonVisibility();
197 }
198
199 bool BaseMultipleFieldsDateAndTimeInputType::hasCustomFocusLogic() const
200 {
201     return false;
202 }
203
204 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerDisabled() const
205 {
206     return element().isDisabledFormControl();
207 }
208
209 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerReadOnly() const
210 {
211     return element().isReadOnly();
212 }
213
214 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectSpinButtonOwner()
215 {
216     if (DateTimeEditElement* edit = dateTimeEditElement())
217         edit->focusIfNoFocus();
218 }
219
220 bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToMouseEvents()
221 {
222     return !element().isDisabledOrReadOnly();
223 }
224
225 bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToWheelEvents()
226 {
227     if (!shouldSpinButtonRespondToMouseEvents())
228         return false;
229     if (DateTimeEditElement* edit = dateTimeEditElement())
230         return edit->hasFocusedField();
231     return false;
232 }
233
234 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepDown()
235 {
236     if (DateTimeEditElement* edit = dateTimeEditElement())
237         edit->stepDown();
238 }
239
240 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepUp()
241 {
242     if (DateTimeEditElement* edit = dateTimeEditElement())
243         edit->stepUp();
244 }
245
246 void BaseMultipleFieldsDateAndTimeInputType::spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch eventDispatch)
247 {
248     if (eventDispatch == SpinButtonElement::EventDispatchAllowed)
249         element().dispatchFormControlChangeEvent();
250 }
251
252 bool BaseMultipleFieldsDateAndTimeInputType::isPickerIndicatorOwnerDisabledOrReadOnly() const
253 {
254     return element().isDisabledOrReadOnly();
255 }
256
257 void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(const String& value)
258 {
259     if (element().isValidValue(value)) {
260         element().setValue(value, DispatchInputAndChangeEvent);
261         return;
262     }
263
264     DateTimeEditElement* edit = this->dateTimeEditElement();
265     if (!edit)
266         return;
267     EventQueueScope scope;
268     DateComponents date;
269     unsigned end;
270     if (date.parseDate(value, 0, end) && end == value.length())
271         edit->setOnlyYearMonthDay(date);
272     element().dispatchFormControlChangeEvent();
273 }
274
275 void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(double value)
276 {
277     ASSERT(std::isfinite(value) || std::isnan(value));
278     if (std::isnan(value))
279         element().setValue(emptyString(), DispatchInputAndChangeEvent);
280     else
281         element().setValueAsNumber(value, ASSERT_NO_EXCEPTION, DispatchInputAndChangeEvent);
282 }
283
284 bool BaseMultipleFieldsDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
285 {
286     return element().setupDateTimeChooserParameters(parameters);
287 }
288
289 BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement& element)
290     : BaseDateAndTimeInputType(element)
291     , m_isDestroyingShadowSubtree(false)
292     , m_pickerIndicatorIsVisible(false)
293     , m_pickerIndicatorIsAlwaysVisible(false)
294 {
295 }
296
297 BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType()
298 {
299 #if !ENABLE(OILPAN)
300     if (SpinButtonElement* element = spinButtonElement())
301         element->removeSpinButtonOwner();
302     if (ClearButtonElement* element = clearButtonElement())
303         element->removeClearButtonOwner();
304     if (DateTimeEditElement* element = dateTimeEditElement())
305         element->removeEditControlOwner();
306     if (PickerIndicatorElement* element = pickerIndicatorElement())
307         element->removePickerIndicatorOwner();
308 #endif
309 }
310
311 String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
312 {
313     return locale().queryString(blink::WebLocalizedString::ValidationBadInputForDateTime);
314 }
315
316 void BaseMultipleFieldsDateAndTimeInputType::blur()
317 {
318     if (DateTimeEditElement* edit = dateTimeEditElement())
319         edit->blurByOwner();
320 }
321
322 PassRefPtr<RenderStyle> BaseMultipleFieldsDateAndTimeInputType::customStyleForRenderer(PassRefPtr<RenderStyle> originalStyle)
323 {
324     EDisplay originalDisplay = originalStyle->display();
325     EDisplay newDisplay = originalDisplay;
326     if (originalDisplay == INLINE || originalDisplay == INLINE_BLOCK)
327         newDisplay = INLINE_FLEX;
328     else if (originalDisplay == BLOCK)
329         newDisplay = FLEX;
330     TextDirection contentDirection = computedTextDirection();
331     if (originalStyle->direction() == contentDirection && originalDisplay == newDisplay)
332         return originalStyle;
333
334     RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
335     style->setDirection(contentDirection);
336     style->setDisplay(newDisplay);
337     style->setUnique();
338     return style.release();
339 }
340
341 void BaseMultipleFieldsDateAndTimeInputType::createShadowSubtree()
342 {
343     ASSERT(element().shadow());
344
345     // Element must not have a renderer here, because if it did
346     // DateTimeEditElement::customStyleForRenderer() is called in appendChild()
347     // before the field wrapper element is created.
348     // FIXME: This code should not depend on such craziness.
349     ASSERT(!element().renderer());
350
351     Document& document = element().document();
352     ContainerNode* container = element().userAgentShadowRoot();
353
354     container->appendChild(DateTimeEditElement::create(document, *this));
355     element().updateView();
356     container->appendChild(ClearButtonElement::create(document, *this));
357     container->appendChild(SpinButtonElement::create(document, *this));
358
359     if (RenderTheme::theme().supportsCalendarPicker(formControlType()))
360         m_pickerIndicatorIsAlwaysVisible = true;
361     container->appendChild(PickerIndicatorElement::create(document, *this));
362     m_pickerIndicatorIsVisible = true;
363     updatePickerIndicatorVisibility();
364 }
365
366 void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree()
367 {
368     ASSERT(!m_isDestroyingShadowSubtree);
369     m_isDestroyingShadowSubtree = true;
370     if (SpinButtonElement* element = spinButtonElement())
371         element->removeSpinButtonOwner();
372     if (ClearButtonElement* element = clearButtonElement())
373         element->removeClearButtonOwner();
374     if (DateTimeEditElement* element = dateTimeEditElement())
375         element->removeEditControlOwner();
376     if (PickerIndicatorElement* element = pickerIndicatorElement())
377         element->removePickerIndicatorOwner();
378
379     // If a field element has focus, set focus back to the <input> itself before
380     // deleting the field. This prevents unnecessary focusout/blur events.
381     if (containsFocusedShadowElement())
382         element().focus();
383
384     BaseDateAndTimeInputType::destroyShadowSubtree();
385     m_isDestroyingShadowSubtree = false;
386 }
387
388 void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusType type)
389 {
390     DateTimeEditElement* edit = dateTimeEditElement();
391     if (!edit || m_isDestroyingShadowSubtree)
392         return;
393     if (type == FocusTypeBackward) {
394         if (element().document().page())
395             element().document().page()->focusController().advanceFocus(type);
396     } else if (type == FocusTypeNone || type == FocusTypeMouse || type == FocusTypePage) {
397         edit->focusByOwner(oldFocusedElement);
398     } else {
399         edit->focusByOwner();
400     }
401 }
402
403 void BaseMultipleFieldsDateAndTimeInputType::forwardEvent(Event* event)
404 {
405     if (SpinButtonElement* element = spinButtonElement()) {
406         element->forwardEvent(event);
407         if (event->defaultHandled())
408             return;
409     }
410
411     if (DateTimeEditElement* edit = dateTimeEditElement())
412         edit->defaultEventHandler(event);
413 }
414
415 void BaseMultipleFieldsDateAndTimeInputType::disabledAttributeChanged()
416 {
417     spinButtonElement()->releaseCapture();
418     clearButtonElement()->releaseCapture();
419     if (DateTimeEditElement* edit = dateTimeEditElement())
420         edit->disabledStateChanged();
421 }
422
423 void BaseMultipleFieldsDateAndTimeInputType::requiredAttributeChanged()
424 {
425     clearButtonElement()->releaseCapture();
426     updateClearButtonVisibility();
427 }
428
429 void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
430 {
431     if (m_pickerIndicatorIsVisible
432         && ((event->keyIdentifier() == "Down" && event->getModifierState("Alt")) || (RenderTheme::theme().shouldOpenPickerWithF4Key() && event->keyIdentifier() == "F4"))) {
433         if (PickerIndicatorElement* element = pickerIndicatorElement())
434             element->openPopup();
435         event->setDefaultHandled();
436     } else {
437         forwardEvent(event);
438     }
439 }
440
441 bool BaseMultipleFieldsDateAndTimeInputType::hasBadInput() const
442 {
443     DateTimeEditElement* edit = dateTimeEditElement();
444     return element().value().isEmpty() && edit && edit->anyEditableFieldsHaveValues();
445 }
446
447 AtomicString BaseMultipleFieldsDateAndTimeInputType::localeIdentifier() const
448 {
449     return element().computeInheritedLanguage();
450 }
451
452 void BaseMultipleFieldsDateAndTimeInputType::editControlDidChangeValueByKeyboard()
453 {
454     element().dispatchFormControlChangeEvent();
455 }
456
457 void BaseMultipleFieldsDateAndTimeInputType::minOrMaxAttributeChanged()
458 {
459     updateView();
460 }
461
462 void BaseMultipleFieldsDateAndTimeInputType::readonlyAttributeChanged()
463 {
464     spinButtonElement()->releaseCapture();
465     clearButtonElement()->releaseCapture();
466     if (DateTimeEditElement* edit = dateTimeEditElement())
467         edit->readOnlyStateChanged();
468 }
469
470 void BaseMultipleFieldsDateAndTimeInputType::restoreFormControlState(const FormControlState& state)
471 {
472     DateTimeEditElement* edit = dateTimeEditElement();
473     if (!edit)
474         return;
475     DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state);
476     edit->setValueAsDateTimeFieldsState(dateTimeFieldsState);
477     element().setValueInternal(sanitizeValue(edit->value()), DispatchNoEvent);
478     updateClearButtonVisibility();
479 }
480
481 FormControlState BaseMultipleFieldsDateAndTimeInputType::saveFormControlState() const
482 {
483     if (DateTimeEditElement* edit = dateTimeEditElement())
484         return edit->valueAsDateTimeFieldsState().saveFormControlState();
485     return FormControlState();
486 }
487
488 void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
489 {
490     InputType::setValue(sanitizedValue, valueChanged, eventBehavior);
491     DateTimeEditElement* edit = dateTimeEditElement();
492     if (valueChanged || (sanitizedValue.isEmpty() && edit && edit->anyEditableFieldsHaveValues())) {
493         element().updateView();
494         element().setNeedsValidityCheck();
495     }
496 }
497
498 void BaseMultipleFieldsDateAndTimeInputType::stepAttributeChanged()
499 {
500     updateView();
501 }
502
503 void BaseMultipleFieldsDateAndTimeInputType::updateView()
504 {
505     DateTimeEditElement* edit = dateTimeEditElement();
506     if (!edit)
507         return;
508
509     DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), createStepRange(AnyIsDefaultStep));
510
511     DateComponents date;
512     bool hasValue = false;
513     if (!element().suggestedValue().isNull())
514         hasValue = parseToDateComponents(element().suggestedValue(), &date);
515     else
516         hasValue = parseToDateComponents(element().value(), &date);
517     if (!hasValue)
518         setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);
519
520     setupLayoutParameters(layoutParameters, date);
521
522     DEFINE_STATIC_LOCAL(AtomicString, datetimeformatAttr, ("datetimeformat", AtomicString::ConstructFromLiteral));
523     edit->setAttribute(datetimeformatAttr, AtomicString(layoutParameters.dateTimeFormat), ASSERT_NO_EXCEPTION);
524     const AtomicString pattern = edit->fastGetAttribute(HTMLNames::patternAttr);
525     if (!pattern.isEmpty())
526         layoutParameters.dateTimeFormat = pattern;
527
528     if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
529         layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;
530
531     if (hasValue)
532         edit->setValueAsDate(layoutParameters, date);
533     else
534         edit->setEmptyValue(layoutParameters, date);
535     updateClearButtonVisibility();
536 }
537
538 void BaseMultipleFieldsDateAndTimeInputType::valueAttributeChanged()
539 {
540     if (!element().hasDirtyValue())
541         updateView();
542 }
543
544 void BaseMultipleFieldsDateAndTimeInputType::listAttributeTargetChanged()
545 {
546     updatePickerIndicatorVisibility();
547 }
548
549 void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility()
550 {
551     if (m_pickerIndicatorIsAlwaysVisible) {
552         showPickerIndicator();
553         return;
554     }
555     if (element().hasValidDataListOptions())
556         showPickerIndicator();
557     else
558         hidePickerIndicator();
559 }
560
561 void BaseMultipleFieldsDateAndTimeInputType::hidePickerIndicator()
562 {
563     if (!m_pickerIndicatorIsVisible)
564         return;
565     m_pickerIndicatorIsVisible = false;
566     ASSERT(pickerIndicatorElement());
567     pickerIndicatorElement()->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
568 }
569
570 void BaseMultipleFieldsDateAndTimeInputType::showPickerIndicator()
571 {
572     if (m_pickerIndicatorIsVisible)
573         return;
574     m_pickerIndicatorIsVisible = true;
575     ASSERT(pickerIndicatorElement());
576     pickerIndicatorElement()->removeInlineStyleProperty(CSSPropertyDisplay);
577 }
578
579 bool BaseMultipleFieldsDateAndTimeInputType::shouldHaveSecondField(const DateComponents& date) const
580 {
581     StepRange stepRange = createStepRange(AnyIsDefaultStep);
582     return date.second() || date.millisecond()
583         || !stepRange.minimum().remainder(static_cast<int>(msPerMinute)).isZero()
584         || !stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
585 }
586
587 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectClearButtonOwner()
588 {
589     element().focus();
590 }
591
592 bool BaseMultipleFieldsDateAndTimeInputType::shouldClearButtonRespondToMouseEvents()
593 {
594     return !element().isDisabledOrReadOnly() && !element().isRequired();
595 }
596
597 void BaseMultipleFieldsDateAndTimeInputType::clearValue()
598 {
599     RefPtrWillBeRawPtr<HTMLInputElement> input(element());
600     input->setValue("", DispatchInputAndChangeEvent);
601     input->updateClearButtonVisibility();
602 }
603
604 void BaseMultipleFieldsDateAndTimeInputType::updateClearButtonVisibility()
605 {
606     ClearButtonElement* clearButton = clearButtonElement();
607     if (!clearButton)
608         return;
609
610     if (element().isRequired() || !dateTimeEditElement()->anyEditableFieldsHaveValues()) {
611         clearButton->setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER);
612         clearButton->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone);
613     } else {
614         clearButton->removeInlineStyleProperty(CSSPropertyOpacity);
615         clearButton->removeInlineStyleProperty(CSSPropertyPointerEvents);
616     }
617 }
618
619 TextDirection BaseMultipleFieldsDateAndTimeInputType::computedTextDirection()
620 {
621     return element().locale().isRTL() ? RTL : LTR;
622 }
623
624 } // namespace blink
625
626 #endif