Changeset 172826
– WebKit ([original](https://trac.webkit.org/changeset/172826)) ([raw](?raw))
| r172817 | r172826 | |
|---|---|---|
| 1 | 2014-08-20 Benjamin Poulain benjamin@webkit.org | |
| 2 | ||
| 3 | CSS: Implement the :placeholder-shown pseudo-class from Selectors Level 4 | |
| 4 | https://bugs.webkit.org/show\_bug.cgi?id=118162 | |
| 5 | ||
| 6 | Reviewed by Antti Koivisto. | |
| 7 | ||
| 8 | Add basic test coverage for common operations: styling, querySelector, CSSOM. | |
| 9 | ||
| 10 | The layout test failure of placeholder-shown-sibling-style-update.html seems unrelated | |
| 11 | to this patch, it fails in many more cases. This will be investigated separately, the failure | |
| 12 | are used as expected values for now. | |
| 13 | ||
| 14 | * fast/css/css-selector-text-expected.txt: | |
| 15 | * fast/css/css-selector-text.html: | |
| 16 | * fast/css/css-set-selector-text-expected.txt: | |
| 17 | * fast/css/css-set-selector-text.html: | |
| 18 | * fast/css/placeholder-shown-basics-expected.html: Added. | |
| 19 | * fast/css/placeholder-shown-basics.html: Added. | |
| 20 | * fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt: Added. | |
| 21 | * fast/selectors/placeholder-shown-long-adjacent-backtracking.html: Added. | |
| 22 | * fast/selectors/placeholder-shown-sibling-style-update-expected.txt: Added. | |
| 23 | * fast/selectors/placeholder-shown-sibling-style-update.html: Added. | |
| 24 | * fast/selectors/placeholder-shown-style-update-expected.txt: Added. | |
| 25 | * fast/selectors/placeholder-shown-style-update.html: Added. | |
| 26 | * fast/selectors/placeholder-shown-with-input-basics-expected.txt: Added. | |
| 27 | * fast/selectors/placeholder-shown-with-input-basics.html: Added. | |
| 28 | * fast/selectors/placeholder-shown-with-textarea-basics-expected.txt: Added. | |
| 29 | * fast/selectors/placeholder-shown-with-textarea-basics.html: Added. | |
| 30 | ||
| 1 | 31 | 2014-08-20 Benjamin Poulain bpoulain@apple.com |
| 2 | 32 |
| r101998 | r172826 | |
|---|---|---|
| 41 | 41 | PASS parseThenSerializeRule(':indeterminate { }') is ':indeterminate { }' |
| 42 | 42 | PASS parseThenSerializeRule(':link { }') is ':link { }' |
| 43 | PASS parseThenSerializeRule(':not(:placeholder-shown) { }') is ':not(:placeholder-shown) { }' | |
| 44 | PASS parseThenSerializeRule(':placeholder-shown { }') is ':placeholder-shown { }' | |
| 43 | 45 | PASS parseThenSerializeRule(':root { }') is ':root { }' |
| 44 | 46 | PASS parseThenSerializeRule(':target { }') is ':target { }' |
| r155263 | r172826 | |
|---|---|---|
| 72 | 72 | testSelectorRoundTrip(":indeterminate"); |
| 73 | 73 | testSelectorRoundTrip(":link"); |
| 74 | testSelectorRoundTrip(":not(:placeholder-shown)"); | |
| 75 | testSelectorRoundTrip(":placeholder-shown"); | |
| 74 | 76 | testSelectorRoundTrip(":root"); |
| 75 | 77 | testSelectorRoundTrip(":target"); |
| r101998 | r172826 | |
|---|---|---|
| 51 | 51 | PASS setThenReadSelectorText(':indeterminate') is ':indeterminate' |
| 52 | 52 | PASS setThenReadSelectorText(':link') is ':link' |
| 53 | PASS setThenReadSelectorText(':not(:placeholder-shown)') is ':not(:placeholder-shown)' | |
| 54 | PASS setThenReadSelectorText(':placeholder-shown') is ':placeholder-shown' | |
| 53 | 55 | PASS setThenReadSelectorText(':root') is ':root' |
| 54 | 56 | PASS setThenReadSelectorText(':target') is ':target' |
| r155263 | r172826 | |
|---|---|---|
| 89 | 89 | testSelectorRoundTrip(":indeterminate"); |
| 90 | 90 | testSelectorRoundTrip(":link"); |
| 91 | testSelectorRoundTrip(":not(:placeholder-shown)"); | |
| 92 | testSelectorRoundTrip(":placeholder-shown"); | |
| 91 | 93 | testSelectorRoundTrip(":root"); |
| 92 | 94 | testSelectorRoundTrip(":target"); |
| r172818 | r172826 | |
|---|---|---|
| 1 | 2014-08-20 Benjamin Poulain benjamin@webkit.org | |
| 2 | ||
| 3 | CSS: Implement the :placeholder-shown pseudo-class from Selectors Level 4 | |
| 4 | https://bugs.webkit.org/show\_bug.cgi?id=118162 | |
| 5 | ||
| 6 | Reviewed by Antti Koivisto. | |
| 7 | ||
| 8 | Previously, HTMLTextFormControlElement was using some mix of its own state | |
| 9 | and style to change the visibility of the placeholder. That approach was a little | |
| 10 | bit too fragile, and we do not want the style to depends on the renderer() since | |
| 11 | that creates circular dependencies. | |
| 12 | ||
| 13 | The biggest change here is refactoring HTMLTextFormControlElement to have | |
| 14 | 1) An explicit "visible placeholder" state. | |
| 15 | 2) Separate the textUpdate() from the visibilityUpdate(). | |
| 16 | 3) Remove the dependencies between the Element's style and the placeholder's style. | |
| 17 | This is done by simply using display:none; on the placeholder so that its parent's visibility | |
| 18 | is irrelevant. | |
| 19 | ||
| 20 | When matching the selector, the style is set as unique since style sharing does not deal with | |
| 21 | the changes of HTMLTextFormControlElement. | |
| 22 | ||
| 23 | Tests: fast/css/placeholder-shown-basics.html | |
| 24 | fast/selectors/placeholder-shown-long-adjacent-backtracking.html | |
| 25 | fast/selectors/placeholder-shown-sibling-style-update.html | |
| 26 | fast/selectors/placeholder-shown-style-update.html | |
| 27 | fast/selectors/placeholder-shown-with-input-basics.html | |
| 28 | fast/selectors/placeholder-shown-with-textarea-basics.html | |
| 29 | ||
| 30 | * css/CSSSelector.cpp: | |
| 31 | (WebCore::CSSSelector::selectorText): | |
| 32 | Add the CSS Selector description for CSSOM. | |
| 33 | ||
| 34 | * css/CSSSelector.h: | |
| 35 | * css/SelectorChecker.cpp: | |
| 36 | (WebCore::SelectorChecker::checkOne): | |
| 37 | * css/SelectorCheckerTestFunctions.h: | |
| 38 | (WebCore::isPlaceholderShown): | |
| 39 | * css/SelectorPseudoClassAndCompatibilityElementMap.in: | |
| 40 | * css/html.css: | |
| 41 | (::-webkit-input-placeholder): | |
| 42 | Previously, the display was forced through the UA stylesheet. Since the display is now part | |
| 43 | of the placeholder visibility, it is explicitly handled by HTMLTextFormControlElement and | |
| 44 | its subclasses. | |
| 45 | ||
| 46 | * cssjit/SelectorCompiler.cpp: | |
| 47 | (WebCore::SelectorCompiler::addPseudoClassType): | |
| 48 | (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching): | |
| 49 | (WebCore::SelectorCompiler::makeUniqueIfNecessaryAndTestIsPlaceholderShown): | |
| 50 | (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown): | |
| 51 | * html/HTMLInputElement.cpp: | |
| 52 | (WebCore::HTMLInputElement::parseAttribute): | |
| 53 | * html/HTMLTextAreaElement.cpp: | |
| 54 | (WebCore::HTMLTextAreaElement::updateValue): | |
| 55 | (WebCore::HTMLTextAreaElement::setValueCommon): | |
| 56 | (WebCore::HTMLTextAreaElement::updatePlaceholderText): | |
| 57 | * html/HTMLTextFormControlElement.cpp: | |
| 58 | (WebCore::HTMLTextFormControlElement::HTMLTextFormControlElement): | |
| 59 | (WebCore::HTMLTextFormControlElement::dispatchFocusEvent): | |
| 60 | (WebCore::HTMLTextFormControlElement::dispatchBlurEvent): | |
| 61 | (WebCore::HTMLTextFormControlElement::placeholderShouldBeVisible): | |
| 62 | (WebCore::HTMLTextFormControlElement::updatePlaceholderVisibility): | |
| 63 | (WebCore::HTMLTextFormControlElement::selectionDirection): | |
| 64 | (WebCore::HTMLTextFormControlElement::restoreCachedSelection): | |
| 65 | (WebCore::HTMLTextFormControlElement::parseAttribute): | |
| 66 | (WebCore::HTMLTextFormControlElement::hidePlaceholder): | |
| 67 | (WebCore::HTMLTextFormControlElement::showPlaceholderIfNecessary): | |
| 68 | * html/HTMLTextFormControlElement.h: | |
| 69 | (WebCore::HTMLTextFormControlElement::isPlaceholderVisible): | |
| 70 | (WebCore::HTMLTextFormControlElement::cachedSelectionDirection): | |
| 71 | * html/TextFieldInputType.cpp: | |
| 72 | (WebCore::TextFieldInputType::updatePlaceholderText): | |
| 73 | (WebCore::TextFieldInputType::subtreeHasChanged): | |
| 74 | (WebCore::TextFieldInputType::updateInnerTextValue): | |
| 75 | * rendering/RenderTextControl.cpp: | |
| 76 | (WebCore::RenderTextControl::styleDidChange): | |
| 77 | * testing/Internals.cpp: | |
| 78 | (WebCore::Internals::visiblePlaceholder): | |
| 79 | ||
| 1 | 80 | 2014-08-20 Mark Rowe mrowe@apple.com |
| 2 | 81 |
| r172817 | r172826 | |
|---|---|---|
| 1853 | 1853 | __ZNK7WebCore23FrameLoaderStateMachine23committingFirstRealLoadEv |
| 1854 | 1854 | __ZNK7WebCore26HTMLTextFormControlElement21lastChangeWasUserEditEv |
| 1855 | ||
| 1856 | 1855 | __ZNK7WebCore26NetscapePlugInStreamLoader6isDoneEv |
| 1857 | 1856 | __ZNK7WebCore27AuthenticationChallengeBase15failureResponseEv |
| r170774 | r172826 | |
|---|---|---|
| 418 | 418 | str.appendLiteral(":optional"); |
| 419 | 419 | break; |
| 420 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 421 | case CSSSelector::PseudoClassPlaceholderShown: | |
| 422 | str.appendLiteral(":placeholder-shown"); | |
| 423 | break; | |
| 424 | #endif | |
| 420 | 425 | case CSSSelector::PseudoClassOutOfRange: |
| 421 | 426 | str.appendLiteral(":out-of-range"); |
| … | … | |
| 462 | 467 | str.appendLiteral(":window-inactive"); |
| 463 | 468 | break; |
| 464 | ||
| 469 | case CSSSelector::PseudoClassUnknown: | |
| 465 | 470 | ASSERT_NOT_REACHED(); |
| 466 | 471 | } |
| r167571 | r172826 | |
|---|---|---|
| 2 | 2 | * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) |
| 3 | 3 | * 1999 Waldo Bastian (bastian@kde.org) |
| 4 | * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. | |
| 4 | * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013, 2014 Apple Inc. All rights reserved. | |
| 5 | 5 | * |
| 6 | 6 | * This library is free software; you can redistribute it and/or |
| … | … | |
| 107 | 107 | PseudoClassDisabled, |
| 108 | 108 | PseudoClassOptional, |
| 109 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 110 | PseudoClassPlaceholderShown, | |
| 111 | #endif | |
| 109 | 112 | PseudoClassRequired, |
| 110 | 113 | PseudoClassReadOnly, |
| r172721 | r172826 | |
|---|---|---|
| 605 | 605 | } |
| 606 | 606 | break; |
| 607 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 608 | case CSSSelector::PseudoClassPlaceholderShown: | |
| 609 | if (m_mode == Mode::ResolvingStyle) { | |
| 610 | if (RenderStyle* style = context.elementStyle ? context.elementStyle : element->renderStyle()) | |
| 611 | style->setUnique(); | |
| 612 | } | |
| 613 | return isPlaceholderShown(element); | |
| 614 | #endif | |
| 607 | 615 | case CSSSelector::PseudoClassNthChild: |
| 608 | 616 | if (!selector->parseNth()) |
| r172663 | r172826 | |
|---|---|---|
| 115 | 115 | } |
| 116 | 116 | |
| 117 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 118 | ALWAYS_INLINE bool isPlaceholderShown(Element* element) | |
| 119 | { | |
| 120 | if (isHTMLTextFormControlElement(*element)) | |
| 121 | return toHTMLTextFormControlElement(*element).isPlaceholderVisible(); | |
| 122 | return false; | |
| 123 | } | |
| 124 | #endif | |
| 125 | ||
| 117 | 126 | ALWAYS_INLINE bool isRequiredFormControl(const Element* element) |
| 118 | 127 | { |
| r167571 | r172826 | |
|---|---|---|
| 42 | 42 | optional |
| 43 | 43 | out-of-range |
| 44 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 45 | placeholder-shown | |
| 46 | #endif | |
| 44 | 47 | read-only |
| 45 | 48 | read-write |
| r172259 | r172826 | |
|---|---|---|
| 612 | 612 | -webkit-text-security: none; |
| 613 | 613 | color: darkGray; |
| 614 | ||
| 615 | 614 | pointer-events: none !important; |
| 616 | 615 | } |
| r172721 | r172826 | |
|---|---|---|
| 245 | 245 | void generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment&); |
| 246 | 246 | void generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment&); |
| 247 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 248 | void generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment&); | |
| 249 | #endif | |
| 247 | 250 | void generateSynchronizeStyleAttribute(Assembler::RegisterID elementDataArraySizeAndFlags); |
| 248 | 251 | void generateSynchronizeAllAnimatedSVGAttribute(Assembler::RegisterID elementDataArraySizeAndFlags); |
| … | … | |
| 537 | 540 | case CSSSelector::PseudoClassLastChild: |
| 538 | 541 | case CSSSelector::PseudoClassOnlyChild: |
| 542 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 543 | case CSSSelector::PseudoClassPlaceholderShown: | |
| 544 | #endif | |
| 539 | 545 | fragment.pseudoClasses.add(type); |
| 540 | 546 | if (selectorContext == SelectorContext::QuerySelector) |
| … | … | |
| 1973 | 1979 | if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassOnlyChild)) |
| 1974 | 1980 | generateElementIsOnlyChild(matchingPostTagNameFailureCases, fragment); |
| 1981 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 1982 | if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassPlaceholderShown)) | |
| 1983 | generateElementHasPlaceholderShown(matchingPostTagNameFailureCases, fragment); | |
| 1984 | #endif | |
| 1975 | 1985 | if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassFirstChild)) |
| 1976 | 1986 | generateElementIsFirstChild(matchingPostTagNameFailureCases, fragment); |
| … | … | |
| 2799 | 2809 | } |
| 2800 | 2810 | |
| 2811 | #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| 2812 | static bool makeUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const CheckingContext* checkingContext) | |
| 2813 | { | |
| 2814 | if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle) { | |
| 2815 | if (RenderStyle* style = element->renderStyle()) | |
| 2816 | style->setUnique(); | |
| 2817 | } | |
| 2818 | return isPlaceholderShown(element); | |
| 2819 | } | |
| 2820 | ||
| 2821 | void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment& fragment) | |
| 2822 | { | |
| 2823 | if (m_selectorContext == SelectorContext::QuerySelector) { | |
| 2824 | FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls); | |
| 2825 | functionCall.setFunctionAddress(isPlaceholderShown); | |
| 2826 | functionCall.setOneArgument(elementAddressRegister); | |
| 2827 | failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero)); | |
| 2828 | return; | |
| 2829 | } | |
| 2830 | ||
| 2831 | if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) { | |
| 2832 | { | |
| 2833 | LocalRegister checkingContext(m_registerAllocator); | |
| 2834 | Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext); | |
| 2835 | addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsUnique()); | |
| 2836 | notResolvingStyle.link(&m_assembler); | |
| 2837 | } | |
| 2838 | ||
| 2839 | FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls); | |
| 2840 | functionCall.setFunctionAddress(isPlaceholderShown); | |
| 2841 | functionCall.setOneArgument(elementAddressRegister); | |
| 2842 | failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero)); | |
| 2843 | } else { | |
| 2844 | Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1); | |
| 2845 | loadCheckingContext(checkingContext); | |
| 2846 | m_registerAllocator.deallocateRegister(checkingContext); | |
| 2847 | ||
| 2848 | FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls); | |
| 2849 | functionCall.setFunctionAddress(makeUniqueIfNecessaryAndTestIsPlaceholderShown); | |
| 2850 | functionCall.setTwoArguments(elementAddressRegister, checkingContext); | |
| 2851 | failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero)); | |
| 2852 | } | |
| 2853 | } | |
| 2854 | #endif | |
| 2855 | ||
| 2801 | 2856 | inline void SelectorCodeGenerator::generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch) |
| 2802 | 2857 | { |
| r172817 | r172826 | |
|---|---|---|
| 637 | 637 | // We only need to setChanged if the form is looking at the default value right now. |
| 638 | 638 | if (!hasDirtyValue()) { |
| 639 | updatePlaceholderVisibility( |
|
| 639 | updatePlaceholderVisibility(); | |
| 640 | 640 | setNeedsStyleRecalc(); |
| 641 | 641 | } |
| r170774 | r172826 | |
|---|---|---|
| 3 | 3 | * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 | 4 | * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. | |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2014 Apple Inc. All rights reserved. | |
| 6 | 6 | * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 | 7 | * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) |
| … | … | |
| 346 | 346 | m_isDirty = true; |
| 347 | 347 | m_wasModifiedByUser = true; |
| 348 | const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility( |
|
| 348 | const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility(); | |
| 349 | 349 | } |
| 350 | 350 | |
| … | … | |
| 386 | 386 | setInnerTextValue(m_value); |
| 387 | 387 | setLastChangeWasNotUserEdit(); |
| 388 | updatePlaceholderVisibility( |
|
| 388 | updatePlaceholderVisibility(); | |
| 389 | 389 | setNeedsStyleRecalc(); |
| 390 | 390 | setFormControlValueMatchesRenderer(true); |
| … | … | |
| 540 | 540 | m_placeholder = placeholder.get(); |
| 541 | 541 | m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); |
| 542 | m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true); | |
| 542 | 543 | userAgentShadowRoot()->insertBefore(m_placeholder, innerTextElement()->nextSibling()); |
| 543 | 544 | } |
| r172817 | r172826 | |
|---|---|---|
| 3 | 3 | * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 | 4 | * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007, 2014 Apple Inc. All rights reserved. | |
| 6 | 6 | * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 | 7 | * |
| … | … | |
| 39 | 39 | #include "HTMLNames.h" |
| 40 | 40 | #include "NodeTraversal.h" |
| 41 | #include "Page.h" | |
| 41 | 42 | #include "RenderBlockFlow.h" |
| 42 | 43 | #include "RenderTextControlSingleLine.h" |
| … | … | |
| 56 | 57 | HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form) |
| 57 | 58 | : HTMLFormControlElementWithState(tagName, document, form) |
| 58 | ||
| 59 | 59 | , m_cachedSelectionStart(-1) |
| 60 | 60 | , m_cachedSelectionEnd(-1) |
| 61 | 61 | , m_cachedSelectionDirection(SelectionHasNoDirection) |
| 62 | , m_lastChangeWasUserEdit(false) | |
| 63 | , m_isPlaceholderVisible(false) | |
| 62 | 64 | { |
| 63 | 65 | } |
| … | … | |
| 89 | 91 | { |
| 90 | 92 | if (supportsPlaceholder()) |
| 91 | updatePlaceholderVisibility( |
|
| 93 | updatePlaceholderVisibility(); | |
| 92 | 94 | handleFocusEvent(oldFocusedElement.get(), direction); |
| 93 | 95 | HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction); |
| … | … | |
| 97 | 99 | { |
| 98 | 100 | if (supportsPlaceholder()) |
| 99 | updatePlaceholderVisibility( |
|
| 101 | updatePlaceholderVisibility(); | |
| 100 | 102 | handleBlurEvent(); |
| 101 | 103 | HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); |
| … | … | |
| 148 | 150 | bool HTMLTextFormControlElement::placeholderShouldBeVisible() const |
| 149 | 151 | { |
| 152 | // This function is used by the style resolver to match the :placeholder-shown pseudo class. | |
| 153 | // Since it is used for styling, it must not use any value depending on the style. | |
| 150 | 154 | return supportsPlaceholder() |
| 151 | 155 | && isEmptyValue() |
| 152 | 156 | && !isPlaceholderEmpty() |
| 153 | && (document().focusedElement() != this | | |
| 154 | && (!renderer() | | |
| 155 | } | |
| 156 | ||
| 157 | void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged) | |
| 158 | { | |
| 159 | if (!supportsPlaceholder()) | |
| 157 | && (document().focusedElement() != this | | |
| 158 | } | |
| 159 | ||
| 160 | void HTMLTextFormControlElement::updatePlaceholderVisibility() | |
| 161 | { | |
| 162 | bool placeHolderWasVisible = m_isPlaceholderVisible; | |
| 163 | m_isPlaceholderVisible = placeholderShouldBeVisible(); | |
| 164 | ||
| 165 | if (placeHolderWasVisible == m_isPlaceholderVisible) | |
| 160 | 166 | return; |
| 161 | if (!placeholderElement() | | |
| 162 | updatePlaceholderText(); | |
| 163 | HTMLElement* placeholder = placeholderElement(); | |
| 164 | if (!placeholder) | |
| 165 | return; | |
| 166 | placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden); | |
| 167 | ||
| 168 | setNeedsStyleRecalc(); | |
| 169 | ||
| 170 | if (HTMLElement* placeholder = placeholderElement()) | |
| 171 | placeholder->setInlineStyleProperty(CSSPropertyDisplay, m_isPlaceholderVisible ? CSSValueBlock : CSSValueNone, true); | |
| 167 | 172 | } |
| 168 | 173 | |
| … | … | |
| 397 | 402 | return directionString(SelectionHasNoDirection); |
| 398 | 403 | if (document().focusedElement() != this && hasCachedSelection()) |
| 399 | return directionString( |
|
| 404 | return directionString(cachedSelectionDirection()); | |
| 400 | 405 | |
| 401 | 406 | return directionString(computeSelectionDirection()); |
| … | … | |
| 467 | 472 | void HTMLTextFormControlElement::restoreCachedSelection() |
| 468 | 473 | { |
| 469 | setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, |
|
| 474 | setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, cachedSelectionDirection()); | |
| 470 | 475 | } |
| 471 | 476 | |
| … | … | |
| 485 | 490 | void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value) |
| 486 | 491 | { |
| 487 | if (name == placeholderAttr) | |
| 488 | updatePlaceholderVisibility(true); | |
| 489 | else | |
| 492 | if (name == placeholderAttr) { | |
| 493 | updatePlaceholderText(); | |
| 494 | updatePlaceholderVisibility(); | |
| 495 | } else | |
| 490 | 496 | HTMLFormControlElementWithState::parseAttribute(name, value); |
| 491 | 497 | } |
| … | … | |
| 627 | 633 | void HTMLTextFormControlElement::hidePlaceholder() |
| 628 | 634 | { |
| 629 | if (!supportsPlaceholder()) | |
| 630 | return; | |
| 631 | HTMLElement* placeholder = placeholderElement(); | |
| 632 | if (!placeholder) { | |
| 633 | updatePlaceholderText(); | |
| 634 | return; | |
| 635 | } | |
| 636 | placeholder->setInlineStyleProperty(CSSPropertyVisibility, ASCIILiteral("hidden")); | |
| 635 | if (HTMLElement* placeholder = placeholderElement()) | |
| 636 | placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden, true); | |
| 637 | 637 | } |
| 638 | 638 | |
| 639 | 639 | void HTMLTextFormControlElement::showPlaceholderIfNecessary() |
| 640 | 640 | { |
| 641 | updatePlaceholderVisibility(false); | |
| 641 | if (HTMLElement* placeholder = placeholderElement()) | |
| 642 | placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueVisible, true); | |
| 642 | 643 | } |
| 643 | 644 | #endif |
| r172817 | r172826 | |
|---|---|---|
| 3 | 3 | * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 | 4 | * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
| 5 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved. | |
| 6 | 6 | * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. |
| 7 | 7 | * |
| … | … | |
| 51 | 51 | |
| 52 | 52 | // The derived class should return true if placeholder processing is needed. |
| 53 | bool isPlaceholderVisible() const { return m_isPlaceholderVisible; } | |
| 53 | 54 | virtual bool supportsPlaceholder() const = 0; |
| 54 | 55 | String strippedPlaceholder() const; |
| 55 | ||
| 56 | 56 | virtual HTMLElement* placeholderElement() const = 0; |
| 57 | void updatePlaceholderVisibility( |
|
| 57 | void updatePlaceholderVisibility(); | |
| 58 | 58 | |
| 59 | 59 | int indexForVisiblePosition(const VisiblePosition&) const; |
| … | … | |
| 121 | 121 | |
| 122 | 122 | private: |
| 123 | TextFieldSelectionDirection cachedSelectionDirection() const { return static_cast(m_cachedSelectionDirection); } | |
| 124 | ||
| 123 | 125 | int computeSelectionStart() const; |
| 124 | 126 | int computeSelectionEnd() const; |
| … | … | |
| 138 | 140 | virtual void handleBlurEvent() { } |
| 139 | 141 | |
| 142 | bool placeholderShouldBeVisible() const; | |
| 143 | ||
| 140 | 144 | String m_textAsOfLastFormControlChangeEvent; |
| 141 | bool m_lastChangeWasUserEdit; | |
| 142 | ||
| 145 | ||
| 143 | 146 | int m_cachedSelectionStart; |
| 144 | 147 | int m_cachedSelectionEnd; |
| 145 | TextFieldSelectionDirection m_cachedSelectionDirection; | |
| 148 | ||
| 149 | unsigned char m_cachedSelectionDirection : 2; | |
| 150 | unsigned char m_lastChangeWasUserEdit : 1; | |
| 151 | unsigned char m_isPlaceholderVisible : 1; | |
| 146 | 152 | }; |
| 147 | 153 |
| r172817 | r172826 | |
|---|---|---|
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 | * Copyright (C) 2011 Apple Inc. All rights reserved. | |
| 3 | * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. | |
| 4 | 4 | * |
| 5 | 5 | * Redistribution and use in source and binary forms, with or without |
| … | … | |
| 410 | 410 | m_placeholder = HTMLDivElement::create(element().document()); |
| 411 | 411 | m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); |
| 412 | m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, element().isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true); | |
| 412 | 413 | element().userAgentShadowRoot()->insertBefore(m_placeholder, m_container ? m_container.get() : innerTextElement(), ASSERT_NO_EXCEPTION); |
| 413 | 414 | } |
| … | … | |
| 439 | 440 | // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent. |
| 440 | 441 | element().setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element().innerTextValue()))); |
| 441 | element().updatePlaceholderVisibility( |
|
| 442 | element().updatePlaceholderVisibility(); | |
| 442 | 443 | // Recalc for :invalid change. |
| 443 | 444 | element().setNeedsStyleRecalc(); |
| … | … | |
| 473 | 474 | // It protects an unacceptable renderer value from being overwritten with the DOM value. |
| 474 | 475 | element().setInnerTextValue(visibleValue()); |
| 475 | element().updatePlaceholderVisibility( |
|
| 476 | element().updatePlaceholderVisibility(); | |
| 476 | 477 | } |
| 477 | 478 | } |
| r170774 | r172826 | |
|---|---|---|
| 1 | 1 | /** |
| 2 | * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | |
| 2 | * Copyright (C) 2006, 2007, 2014 Apple Inc. All rights reserved. | |
| 3 | 3 | * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) |
| 4 | 4 | * |
| … | … | |
| 71 | 71 | innerTextRenderer->setStyle(createInnerTextStyle(&style())); |
| 72 | 72 | } |
| 73 | textFormControlElement().updatePlaceholderVisibility( |
|
| 73 | textFormControlElement().updatePlaceholderVisibility(); | |
| 74 | 74 | } |
| 75 | 75 |
| r172817 | r172826 | |
|---|---|---|
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 | * Copyright (C) 2013 Apple Inc. All rights reserved. | |
| 3 | * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. | |
| 4 | 4 | * |
| 5 | 5 | * Redistribution and use in source and binary forms, with or without |
| … | … | |
| 618 | 618 | { |
| 619 | 619 | if (element && isHTMLTextFormControlElement(*element)) { |
| 620 | if (toHTMLTextFormControlElement(*element).placeholderShouldBeVisible()) | |
| 621 | return toHTMLTextFormControlElement(*element).placeholderElement()->textContent(); | |
| 620 | const HTMLTextFormControlElement& textFormControlElement = toHTMLTextFormControlElement(*element); | |
| 621 | if (!textFormControlElement.isPlaceholderVisible()) | |
| 622 | return String(); | |
| 623 | if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement()) | |
| 624 | return placeholderElement->textContent(); | |
| 622 | 625 | } |
| 623 | 626 |
| r172817 | r172826 | |
|---|---|---|
| 263 | 263 | symbolWithPointer(?pageNumberForElement@PrintContext@WebCore@@SAHPAVElement@2@ABVFloatSize@2@@Z, ?pageNumberForElement@PrintContext@WebCore@@SAHPEAVElement@2@AEBVFloatSize@2@@Z) |
| 264 | 264 | symbolWithPointer(?paintControlTints@FrameView@WebCore@@AAEXXZ, ?paintControlTints@FrameView@WebCore@@AEAAXXZ) |
| 265 | ||
| 266 | 265 | symbolWithPointer(?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PAVContainerNode@2@HH_N@Z, ?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PEAVContainerNode@2@HH_N@Z) |
| 267 | 266 | symbolWithPointer(?rectBasedTestResult@HitTestResult@WebCore@@QBEABV?$ListHashSet@V?$RefPtr@VNode@WebCore@@@WTF@@$0BAA@U?$PtrHash@V?$RefPtr@VNode@WebCore@@@WTF@@@2@@WTF@@XZ, ?rectBasedTestResult@HitTestResult@WebCore@@QEBAAEBV?$ListHashSet@V?$RefPtr@VNode@WebCore@@@WTF@@$0BAA@U?$PtrHash@V?$RefPtr@VNode@WebCore@@@WTF@@@2@@WTF@@XZ) |