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 WebCore {
55
56 class DateTimeFormatValidator : public DateTimeFormat::TokenHandler {
57 public:
DateTimeFormatValidator()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;
visitLiteral(const String &)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
visitField(DateTimeFormat::FieldType fieldType,int)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
validateFormat(const String & format,const BaseMultipleFieldsDateAndTimeInputType & inputType)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
dateTimeEditElement() const130 DateTimeEditElement* BaseMultipleFieldsDateAndTimeInputType::dateTimeEditElement() const
131 {
132 return toDateTimeEditElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::dateTimeEdit()));
133 }
134
spinButtonElement() const135 SpinButtonElement* BaseMultipleFieldsDateAndTimeInputType::spinButtonElement() const
136 {
137 return toSpinButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::spinButton()));
138 }
139
clearButtonElement() const140 ClearButtonElement* BaseMultipleFieldsDateAndTimeInputType::clearButtonElement() const
141 {
142 return toClearButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::clearButton()));
143 }
144
pickerIndicatorElement() const145 PickerIndicatorElement* BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorElement() const
146 {
147 return toPickerIndicatorElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::pickerIndicator()));
148 }
149
containsFocusedShadowElement() const150 inline bool BaseMultipleFieldsDateAndTimeInputType::containsFocusedShadowElement() const
151 {
152 return element().userAgentShadowRoot()->contains(element().document().focusedElement());
153 }
154
didBlurFromControl()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
didFocusOnControl()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
editControlValueChanged()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
hasCustomFocusLogic() const199 bool BaseMultipleFieldsDateAndTimeInputType::hasCustomFocusLogic() const
200 {
201 return false;
202 }
203
isEditControlOwnerDisabled() const204 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerDisabled() const
205 {
206 return element().isDisabledFormControl();
207 }
208
isEditControlOwnerReadOnly() const209 bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerReadOnly() const
210 {
211 return element().isReadOnly();
212 }
213
focusAndSelectSpinButtonOwner()214 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectSpinButtonOwner()
215 {
216 if (DateTimeEditElement* edit = dateTimeEditElement())
217 edit->focusIfNoFocus();
218 }
219
shouldSpinButtonRespondToMouseEvents()220 bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToMouseEvents()
221 {
222 return !element().isDisabledOrReadOnly();
223 }
224
shouldSpinButtonRespondToWheelEvents()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
spinButtonStepDown()234 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepDown()
235 {
236 if (DateTimeEditElement* edit = dateTimeEditElement())
237 edit->stepDown();
238 }
239
spinButtonStepUp()240 void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepUp()
241 {
242 if (DateTimeEditElement* edit = dateTimeEditElement())
243 edit->stepUp();
244 }
245
spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch eventDispatch)246 void BaseMultipleFieldsDateAndTimeInputType::spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch eventDispatch)
247 {
248 if (eventDispatch == SpinButtonElement::EventDispatchAllowed)
249 element().dispatchFormControlChangeEvent();
250 }
251
isPickerIndicatorOwnerDisabledOrReadOnly() const252 bool BaseMultipleFieldsDateAndTimeInputType::isPickerIndicatorOwnerDisabledOrReadOnly() const
253 {
254 return element().isDisabledOrReadOnly();
255 }
256
pickerIndicatorChooseValue(const String & value)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 DateComponents date;
268 unsigned end;
269 if (date.parseDate(value, 0, end) && end == value.length())
270 edit->setOnlyYearMonthDay(date);
271 element().dispatchFormControlChangeEvent();
272 }
273
pickerIndicatorChooseValue(double value)274 void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(double value)
275 {
276 ASSERT(std::isfinite(value) || std::isnan(value));
277 if (std::isnan(value))
278 element().setValue(emptyString(), DispatchInputAndChangeEvent);
279 else
280 element().setValueAsNumber(value, ASSERT_NO_EXCEPTION, DispatchInputAndChangeEvent);
281 }
282
setupDateTimeChooserParameters(DateTimeChooserParameters & parameters)283 bool BaseMultipleFieldsDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
284 {
285 return element().setupDateTimeChooserParameters(parameters);
286 }
287
BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement & element)288 BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement& element)
289 : BaseDateAndTimeInputType(element)
290 , m_isDestroyingShadowSubtree(false)
291 , m_pickerIndicatorIsVisible(false)
292 , m_pickerIndicatorIsAlwaysVisible(false)
293 {
294 }
295
~BaseMultipleFieldsDateAndTimeInputType()296 BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType()
297 {
298 #if !ENABLE(OILPAN)
299 if (SpinButtonElement* element = spinButtonElement())
300 element->removeSpinButtonOwner();
301 if (ClearButtonElement* element = clearButtonElement())
302 element->removeClearButtonOwner();
303 if (DateTimeEditElement* element = dateTimeEditElement())
304 element->removeEditControlOwner();
305 if (PickerIndicatorElement* element = pickerIndicatorElement())
306 element->removePickerIndicatorOwner();
307 #endif
308 }
309
badInputText() const310 String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
311 {
312 return locale().queryString(blink::WebLocalizedString::ValidationBadInputForDateTime);
313 }
314
blur()315 void BaseMultipleFieldsDateAndTimeInputType::blur()
316 {
317 if (DateTimeEditElement* edit = dateTimeEditElement())
318 edit->blurByOwner();
319 }
320
customStyleForRenderer(PassRefPtr<RenderStyle> originalStyle)321 PassRefPtr<RenderStyle> BaseMultipleFieldsDateAndTimeInputType::customStyleForRenderer(PassRefPtr<RenderStyle> originalStyle)
322 {
323 EDisplay originalDisplay = originalStyle->display();
324 EDisplay newDisplay = originalDisplay;
325 if (originalDisplay == INLINE || originalDisplay == INLINE_BLOCK)
326 newDisplay = INLINE_FLEX;
327 else if (originalDisplay == BLOCK)
328 newDisplay = FLEX;
329 TextDirection contentDirection = element().locale().isRTL() ? RTL : LTR;
330 if (originalStyle->direction() == contentDirection && originalDisplay == newDisplay)
331 return originalStyle;
332
333 RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
334 style->setDirection(contentDirection);
335 style->setDisplay(newDisplay);
336 style->setUnique();
337 return style.release();
338 }
339
createShadowSubtree()340 void BaseMultipleFieldsDateAndTimeInputType::createShadowSubtree()
341 {
342 ASSERT(element().shadow());
343
344 // Element must not have a renderer here, because if it did
345 // DateTimeEditElement::customStyleForRenderer() is called in appendChild()
346 // before the field wrapper element is created.
347 // FIXME: This code should not depend on such craziness.
348 ASSERT(!element().renderer());
349
350 Document& document = element().document();
351 ContainerNode* container = element().userAgentShadowRoot();
352
353 container->appendChild(DateTimeEditElement::create(document, *this));
354 element().updateView();
355 container->appendChild(ClearButtonElement::create(document, *this));
356 container->appendChild(SpinButtonElement::create(document, *this));
357
358 if (RenderTheme::theme().supportsCalendarPicker(formControlType()))
359 m_pickerIndicatorIsAlwaysVisible = true;
360 container->appendChild(PickerIndicatorElement::create(document, *this));
361 m_pickerIndicatorIsVisible = true;
362 updatePickerIndicatorVisibility();
363 }
364
destroyShadowSubtree()365 void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree()
366 {
367 ASSERT(!m_isDestroyingShadowSubtree);
368 m_isDestroyingShadowSubtree = true;
369 if (SpinButtonElement* element = spinButtonElement())
370 element->removeSpinButtonOwner();
371 if (ClearButtonElement* element = clearButtonElement())
372 element->removeClearButtonOwner();
373 if (DateTimeEditElement* element = dateTimeEditElement())
374 element->removeEditControlOwner();
375 if (PickerIndicatorElement* element = pickerIndicatorElement())
376 element->removePickerIndicatorOwner();
377
378 // If a field element has focus, set focus back to the <input> itself before
379 // deleting the field. This prevents unnecessary focusout/blur events.
380 if (containsFocusedShadowElement())
381 element().focus();
382
383 BaseDateAndTimeInputType::destroyShadowSubtree();
384 m_isDestroyingShadowSubtree = false;
385 }
386
handleFocusEvent(Element * oldFocusedElement,FocusType type)387 void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusType type)
388 {
389 DateTimeEditElement* edit = dateTimeEditElement();
390 if (!edit || m_isDestroyingShadowSubtree)
391 return;
392 if (type == FocusTypeBackward) {
393 if (element().document().page())
394 element().document().page()->focusController().advanceFocus(type);
395 } else if (type == FocusTypeNone || type == FocusTypeMouse || type == FocusTypePage) {
396 edit->focusByOwner(oldFocusedElement);
397 } else {
398 edit->focusByOwner();
399 }
400 }
401
forwardEvent(Event * event)402 void BaseMultipleFieldsDateAndTimeInputType::forwardEvent(Event* event)
403 {
404 if (SpinButtonElement* element = spinButtonElement()) {
405 element->forwardEvent(event);
406 if (event->defaultHandled())
407 return;
408 }
409
410 if (DateTimeEditElement* edit = dateTimeEditElement())
411 edit->defaultEventHandler(event);
412 }
413
disabledAttributeChanged()414 void BaseMultipleFieldsDateAndTimeInputType::disabledAttributeChanged()
415 {
416 spinButtonElement()->releaseCapture();
417 clearButtonElement()->releaseCapture();
418 if (DateTimeEditElement* edit = dateTimeEditElement())
419 edit->disabledStateChanged();
420 }
421
requiredAttributeChanged()422 void BaseMultipleFieldsDateAndTimeInputType::requiredAttributeChanged()
423 {
424 clearButtonElement()->releaseCapture();
425 updateClearButtonVisibility();
426 }
427
handleKeydownEvent(KeyboardEvent * event)428 void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
429 {
430 if (m_pickerIndicatorIsVisible
431 && ((event->keyIdentifier() == "Down" && event->getModifierState("Alt")) || (RenderTheme::theme().shouldOpenPickerWithF4Key() && event->keyIdentifier() == "F4"))) {
432 if (PickerIndicatorElement* element = pickerIndicatorElement())
433 element->openPopup();
434 event->setDefaultHandled();
435 } else {
436 forwardEvent(event);
437 }
438 }
439
hasBadInput() const440 bool BaseMultipleFieldsDateAndTimeInputType::hasBadInput() const
441 {
442 DateTimeEditElement* edit = dateTimeEditElement();
443 return element().value().isEmpty() && edit && edit->anyEditableFieldsHaveValues();
444 }
445
localeIdentifier() const446 AtomicString BaseMultipleFieldsDateAndTimeInputType::localeIdentifier() const
447 {
448 return element().computeInheritedLanguage();
449 }
450
editControlDidChangeValueByKeyboard()451 void BaseMultipleFieldsDateAndTimeInputType::editControlDidChangeValueByKeyboard()
452 {
453 element().dispatchFormControlChangeEvent();
454 }
455
minOrMaxAttributeChanged()456 void BaseMultipleFieldsDateAndTimeInputType::minOrMaxAttributeChanged()
457 {
458 updateView();
459 }
460
readonlyAttributeChanged()461 void BaseMultipleFieldsDateAndTimeInputType::readonlyAttributeChanged()
462 {
463 spinButtonElement()->releaseCapture();
464 clearButtonElement()->releaseCapture();
465 if (DateTimeEditElement* edit = dateTimeEditElement())
466 edit->readOnlyStateChanged();
467 }
468
restoreFormControlState(const FormControlState & state)469 void BaseMultipleFieldsDateAndTimeInputType::restoreFormControlState(const FormControlState& state)
470 {
471 DateTimeEditElement* edit = dateTimeEditElement();
472 if (!edit)
473 return;
474 DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state);
475 edit->setValueAsDateTimeFieldsState(dateTimeFieldsState);
476 element().setValueInternal(sanitizeValue(edit->value()), DispatchNoEvent);
477 updateClearButtonVisibility();
478 }
479
saveFormControlState() const480 FormControlState BaseMultipleFieldsDateAndTimeInputType::saveFormControlState() const
481 {
482 if (DateTimeEditElement* edit = dateTimeEditElement())
483 return edit->valueAsDateTimeFieldsState().saveFormControlState();
484 return FormControlState();
485 }
486
setValue(const String & sanitizedValue,bool valueChanged,TextFieldEventBehavior eventBehavior)487 void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
488 {
489 InputType::setValue(sanitizedValue, valueChanged, eventBehavior);
490 DateTimeEditElement* edit = dateTimeEditElement();
491 if (valueChanged || (sanitizedValue.isEmpty() && edit && edit->anyEditableFieldsHaveValues())) {
492 element().updateView();
493 element().setNeedsValidityCheck();
494 }
495 }
496
shouldUseInputMethod() const497 bool BaseMultipleFieldsDateAndTimeInputType::shouldUseInputMethod() const
498 {
499 return false;
500 }
501
stepAttributeChanged()502 void BaseMultipleFieldsDateAndTimeInputType::stepAttributeChanged()
503 {
504 updateView();
505 }
506
updateView()507 void BaseMultipleFieldsDateAndTimeInputType::updateView()
508 {
509 DateTimeEditElement* edit = dateTimeEditElement();
510 if (!edit)
511 return;
512
513 DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), createStepRange(AnyIsDefaultStep));
514
515 DateComponents date;
516 bool hasValue = false;
517 if (!element().suggestedValue().isNull())
518 hasValue = parseToDateComponents(element().suggestedValue(), &date);
519 else
520 hasValue = parseToDateComponents(element().value(), &date);
521 if (!hasValue)
522 setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);
523
524 setupLayoutParameters(layoutParameters, date);
525
526 DEFINE_STATIC_LOCAL(AtomicString, datetimeformatAttr, ("datetimeformat", AtomicString::ConstructFromLiteral));
527 edit->setAttribute(datetimeformatAttr, AtomicString(layoutParameters.dateTimeFormat), ASSERT_NO_EXCEPTION);
528 const AtomicString pattern = edit->fastGetAttribute(HTMLNames::patternAttr);
529 if (!pattern.isEmpty())
530 layoutParameters.dateTimeFormat = pattern;
531
532 if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
533 layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;
534
535 if (hasValue)
536 edit->setValueAsDate(layoutParameters, date);
537 else
538 edit->setEmptyValue(layoutParameters, date);
539 updateClearButtonVisibility();
540 }
541
valueAttributeChanged()542 void BaseMultipleFieldsDateAndTimeInputType::valueAttributeChanged()
543 {
544 if (!element().hasDirtyValue())
545 updateView();
546 }
547
listAttributeTargetChanged()548 void BaseMultipleFieldsDateAndTimeInputType::listAttributeTargetChanged()
549 {
550 updatePickerIndicatorVisibility();
551 }
552
updatePickerIndicatorVisibility()553 void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility()
554 {
555 if (m_pickerIndicatorIsAlwaysVisible) {
556 showPickerIndicator();
557 return;
558 }
559 if (element().hasValidDataListOptions())
560 showPickerIndicator();
561 else
562 hidePickerIndicator();
563 }
564
hidePickerIndicator()565 void BaseMultipleFieldsDateAndTimeInputType::hidePickerIndicator()
566 {
567 if (!m_pickerIndicatorIsVisible)
568 return;
569 m_pickerIndicatorIsVisible = false;
570 ASSERT(pickerIndicatorElement());
571 pickerIndicatorElement()->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
572 }
573
showPickerIndicator()574 void BaseMultipleFieldsDateAndTimeInputType::showPickerIndicator()
575 {
576 if (m_pickerIndicatorIsVisible)
577 return;
578 m_pickerIndicatorIsVisible = true;
579 ASSERT(pickerIndicatorElement());
580 pickerIndicatorElement()->removeInlineStyleProperty(CSSPropertyDisplay);
581 }
582
shouldHaveSecondField(const DateComponents & date) const583 bool BaseMultipleFieldsDateAndTimeInputType::shouldHaveSecondField(const DateComponents& date) const
584 {
585 StepRange stepRange = createStepRange(AnyIsDefaultStep);
586 return date.second() || date.millisecond()
587 || !stepRange.minimum().remainder(static_cast<int>(msPerMinute)).isZero()
588 || !stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
589 }
590
focusAndSelectClearButtonOwner()591 void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectClearButtonOwner()
592 {
593 element().focus();
594 }
595
shouldClearButtonRespondToMouseEvents()596 bool BaseMultipleFieldsDateAndTimeInputType::shouldClearButtonRespondToMouseEvents()
597 {
598 return !element().isDisabledOrReadOnly() && !element().isRequired();
599 }
600
clearValue()601 void BaseMultipleFieldsDateAndTimeInputType::clearValue()
602 {
603 RefPtrWillBeRawPtr<HTMLInputElement> input(element());
604 input->setValue("", DispatchInputAndChangeEvent);
605 input->updateClearButtonVisibility();
606 }
607
updateClearButtonVisibility()608 void BaseMultipleFieldsDateAndTimeInputType::updateClearButtonVisibility()
609 {
610 ClearButtonElement* clearButton = clearButtonElement();
611 if (!clearButton)
612 return;
613
614 if (element().isRequired() || !dateTimeEditElement()->anyEditableFieldsHaveValues()) {
615 clearButton->setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER);
616 clearButton->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone);
617 } else {
618 clearButton->removeInlineStyleProperty(CSSPropertyOpacity);
619 clearButton->removeInlineStyleProperty(CSSPropertyPointerEvents);
620 }
621 }
622
623 } // namespace WebCore
624
625 #endif
626