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