Changeset 87980 in webkit
- Timestamp:
- Jun 2, 2011, 6:15:25 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r87979 r87980 1 2011-06-02 Kent Tamura <tkent@chromium.org> 2 3 Reviewed by Dimitri Glazkov. 4 5 REGRESSION(r87014): Cloned text <input> doesn't work well. 6 https://bugs.webkit.org/show_bug.cgi?id=61909 7 8 * fast/forms/textfield-clone-expected.txt: Added. 9 * fast/forms/textfield-clone.html: Added. 10 1 11 2011-06-02 Adam Barth <abarth@webkit.org> 2 12 -
trunk/Source/WebCore/ChangeLog
r87978 r87980 1 2011-06-02 Kent Tamura <tkent@chromium.org> 2 3 Reviewed by Dimitri Glazkov. 4 5 REGRESSION(r87014): Cloned text <input> doesn't work well. 6 https://bugs.webkit.org/show_bug.cgi?id=61909 7 8 The default implementation of Element::cloneNode() creates a clone 9 node by Document::createElement(). So, if a customized class is used for 10 shadow nodes, cloneNode() doesn't create a node of the correct class. 11 Such custom classes need to override Element:: 12 cloneElementWithoutAttributesAndChildren(). 13 14 TextFieldInputType and SearchInputType had references to shadow nodes 15 initialized in createShadowSubtree(). However createShadowSubtree() is 16 not called if the host node is cloned. The accessors for shadow nodes 17 should search a shadow tree. 18 19 Test: fast/forms/textfield-clone.html 20 21 * html/SearchInputType.cpp: 22 Remove data members for shadow nodes, and the accessors search the 23 shadow tree for the requested node by TreeScope::getElementById(). 24 (WebCore::SearchInputType::SearchInputType): 25 (WebCore::innerBlockId): 26 (WebCore::resultButtonId): 27 (WebCore::cancelButtonId): 28 (WebCore::SearchInputType::createShadowSubtree): 29 (WebCore::SearchInputType::innerBlockElement): 30 (WebCore::SearchInputType::resultsButtonElement): 31 (WebCore::SearchInputType::cancelButtonElement): 32 * html/SearchInputType.h: 33 * html/TextFieldInputType.cpp: ditto. 34 (WebCore::TextFieldInputType::TextFieldInputType): 35 (WebCore::TextFieldInputType::innerTextId): 36 (WebCore::spinButtonId): 37 (WebCore::TextFieldInputType::speechButtonId): 38 (WebCore::TextFieldInputType::appendChildAndSetId): 39 (WebCore::TextFieldInputType::createShadowSubtree): 40 (WebCore::TextFieldInputType::getShadowElementById): 41 (WebCore::TextFieldInputType::innerTextElement): 42 (WebCore::TextFieldInputType::innerSpinButtonElement): 43 (WebCore::TextFieldInputType::speechButtonElement): 44 * html/TextFieldInputType.h: 45 * html/shadow/TextControlInnerElements.cpp: 46 Overrides cloneElementWithoutAttributesAndChildren() in order that cloneNode() 47 produces an instance of the correct class. 48 (WebCore::TextControlInnerElement::cloneElementWithoutAttributesAndChildren): 49 (WebCore::TextControlInnerTextElement::cloneElementWithoutAttributesAndChildren): 50 (WebCore::SearchFieldResultsButtonElement::cloneElementWithoutAttributesAndChildren): 51 (WebCore::SearchFieldCancelButtonElement::cloneElementWithoutAttributesAndChildren): 52 (WebCore::SpinButtonElement::cloneElementWithoutAttributesAndChildren): 53 (WebCore::InputFieldSpeechButtonElement::cloneElementWithoutAttributesAndChildren): 54 * html/shadow/TextControlInnerElements.h: 55 1 56 2011-05-28 Martin Robinson <mrobinson@igalia.com> 2 57 -
trunk/Source/WebCore/html/SearchInputType.cpp
r87067 r87980 41 41 inline SearchInputType::SearchInputType(HTMLInputElement* element) 42 42 : BaseTextInputType(element) 43 , m_innerBlock(0)44 , m_resultsButton(0)45 , m_cancelButton(0)46 43 { 47 44 } … … 67 64 } 68 65 66 static const AtomicString& innerBlockId() 67 { 68 DEFINE_STATIC_LOCAL(AtomicString, id, ("innerBlock")); 69 return id; 70 } 71 72 static const AtomicString& resultButtonId() 73 { 74 DEFINE_STATIC_LOCAL(AtomicString, id, ("resultButton")); 75 return id; 76 } 77 78 static const AtomicString& cancelButtonId() 79 { 80 DEFINE_STATIC_LOCAL(AtomicString, id, ("cancelButton")); 81 return id; 82 } 83 69 84 void SearchInputType::createShadowSubtree() 70 85 { 71 ASSERT(!m_innerBlock);72 ASSERT(!innerTextElement());73 ASSERT(!m_resultsButton);74 ASSERT(!m_cancelButton);75 76 ExceptionCode ec = 0;77 86 Document* document = element()->document(); 78 87 RefPtr<HTMLElement> inner = TextControlInnerElement::create(document); 79 m_innerBlock = inner.get();80 element()->ensureShadowRoot()->appendChild(inner.release(), ec);88 HTMLElement* innerBlock = inner.get(); 89 appendChildAndSetId(element()->ensureShadowRoot(), inner.release(), innerBlockId()); 81 90 82 91 #if ENABLE(INPUT_SPEECH) 83 if (element()->isSpeechEnabled()) { 84 RefPtr<HTMLElement> speech = InputFieldSpeechButtonElement::create(document); 85 setSpeechButtonElement(speech.get()); 86 element()->ensureShadowRoot()->appendChild(speech.release(), ec); 87 } 92 if (element()->isSpeechEnabled()) 93 appendChildAndSetId(element()->ensureShadowRoot(), InputFieldSpeechButtonElement::create(document), speechButtonId()); 88 94 #endif 89 95 90 RefPtr<HTMLElement> results = SearchFieldResultsButtonElement::create(document); 91 m_resultsButton = results.get(); 92 m_innerBlock->appendChild(results.release(), ec); 93 94 RefPtr<HTMLElement> innerText = TextControlInnerTextElement::create(document); 95 setInnerTextElement(innerText.get()); 96 m_innerBlock->appendChild(innerText.release(), ec); 97 98 RefPtr<HTMLElement> cancel = SearchFieldCancelButtonElement::create(element()->document()); 99 m_cancelButton = cancel.get(); 100 m_innerBlock->appendChild(cancel.release(), ec); 96 appendChildAndSetId(innerBlock, SearchFieldResultsButtonElement::create(document), resultButtonId()); 97 appendChildAndSetId(innerBlock, TextControlInnerTextElement::create(document), innerTextId()); 98 appendChildAndSetId(innerBlock, SearchFieldCancelButtonElement::create(document), cancelButtonId()); 101 99 } 102 100 103 void SearchInputType::destroyShadowSubtree() 101 HTMLElement* SearchInputType::innerBlockElement() const 104 102 { 105 TextFieldInputType::destroyShadowSubtree(); 106 m_innerBlock = 0; 107 m_resultsButton = 0; 108 m_cancelButton = 0; 103 return getShadowElementById(innerBlockId()); 109 104 } 110 105 106 HTMLElement* SearchInputType::resultsButtonElement() const 107 { 108 return getShadowElementById(resultButtonId()); 109 } 110 111 HTMLElement* SearchInputType::cancelButtonElement() const 112 { 113 return getShadowElementById(cancelButtonId()); 114 } 111 115 112 116 } // namespace WebCore -
trunk/Source/WebCore/html/SearchInputType.h
r87067 r87980 36 36 namespace WebCore { 37 37 38 class SearchFieldCancelButtonElement;39 class SearchFieldResultsButtonElement;40 41 38 class SearchInputType : public BaseTextInputType { 42 39 public: 43 40 static PassOwnPtr<InputType> create(HTMLInputElement*); 44 45 protected:46 virtual void createShadowSubtree();47 virtual void destroyShadowSubtree();48 41 49 42 private: … … 52 45 virtual bool shouldRespectSpeechAttribute(); 53 46 virtual bool isSearchField() const; 54 virtual HTMLElement* innerBlockElement() const { return m_innerBlock; } 55 virtual HTMLElement* resultsButtonElement() const { return m_resultsButton; } 56 virtual HTMLElement* cancelButtonElement() const { return m_cancelButton; } 57 58 HTMLElement* m_innerBlock; 59 HTMLElement* m_resultsButton; 60 HTMLElement* m_cancelButton; 47 virtual void createShadowSubtree(); 48 virtual HTMLElement* innerBlockElement() const; 49 virtual HTMLElement* resultsButtonElement() const; 50 virtual HTMLElement* cancelButtonElement() const; 61 51 }; 62 52 -
trunk/Source/WebCore/html/TextFieldInputType.cpp
r87881 r87980 36 36 #include "Frame.h" 37 37 #include "HTMLInputElement.h" 38 #include "HTMLNames.h" 38 39 #include "KeyboardEvent.h" 39 40 #include "RenderTextControlSingleLine.h" … … 48 49 namespace WebCore { 49 50 51 using namespace HTMLNames; 52 50 53 TextFieldInputType::TextFieldInputType(HTMLInputElement* element) 51 54 : InputType(element) 52 , m_innerText(0)53 , m_innerSpinButton(0)54 #if ENABLE(INPUT_SPEECH)55 , m_speechButton(0)56 #endif57 55 { 58 56 } … … 130 128 } 131 129 130 const AtomicString& TextFieldInputType::innerTextId() const 131 { 132 DEFINE_STATIC_LOCAL(AtomicString, id, ("innerText")); 133 return id; 134 } 135 136 static const AtomicString& spinButtonId() 137 { 138 DEFINE_STATIC_LOCAL(AtomicString, id, ("spinButton")); 139 return id; 140 } 141 142 #if ENABLE(INPUT_SPEECH) 143 const AtomicString& TextFieldInputType::speechButtonId() const 144 { 145 DEFINE_STATIC_LOCAL(AtomicString, id, ("speechButton")); 146 return id; 147 } 148 #endif 149 150 void TextFieldInputType::appendChildAndSetId(ContainerNode* parent, PassRefPtr<HTMLElement> child, const AtomicString& id) 151 { 152 ExceptionCode ec = 0; 153 child->setAttribute(idAttr, id); 154 parent->appendChild(child, ec); 155 } 156 132 157 void TextFieldInputType::createShadowSubtree() 133 158 { 134 ASSERT(!m_innerText); 135 ASSERT(!m_innerSpinButton); 136 137 bool shouldHaveSpinButton = RenderTheme::themeForPage(element()->document()->page())->shouldHaveSpinButton(element()); 159 Document* document = element()->document(); 160 bool shouldHaveSpinButton = RenderTheme::themeForPage(document->page())->shouldHaveSpinButton(element()); 138 161 bool hasDecorations = shouldHaveSpinButton; 139 162 #if ENABLE(INPUT_SPEECH) … … 142 165 #endif 143 166 144 ExceptionCode ec = 0; 145 Document* document = element()->document(); 146 RefPtr<HTMLElement> innerText = TextControlInnerTextElement::create(document); 147 m_innerText = innerText.get(); 148 element()->ensureShadowRoot()->appendChild(innerText.release(), ec); 167 ShadowRoot* shadowRoot = element()->ensureShadowRoot(); 168 appendChildAndSetId(shadowRoot, TextControlInnerTextElement::create(document), innerTextId()); 149 169 if (!hasDecorations) 150 170 return; 151 171 152 172 #if ENABLE(INPUT_SPEECH) 153 ASSERT(!m_speechButton); 154 if (element()->isSpeechEnabled()) { 155 RefPtr<HTMLElement> speech = InputFieldSpeechButtonElement::create(document); 156 m_speechButton = speech.get(); 157 element()->ensureShadowRoot()->appendChild(speech.release(), ec); 158 } 159 #endif 160 161 if (shouldHaveSpinButton) { 162 RefPtr<HTMLElement> inner = SpinButtonElement::create(document); 163 m_innerSpinButton = inner.get(); 164 element()->ensureShadowRoot()->appendChild(inner.release(), ec); 165 } 166 } 167 168 void TextFieldInputType::destroyShadowSubtree() 169 { 170 InputType::destroyShadowSubtree(); 171 m_innerText = 0; 172 #if ENABLE(INPUT_SPEECH) 173 m_speechButton = 0; 174 #endif 175 m_innerSpinButton = 0; 176 } 173 if (element()->isSpeechEnabled()) 174 appendChildAndSetId(shadowRoot, InputFieldSpeechButtonElement::create(document), speechButtonId()); 175 #endif 176 177 if (shouldHaveSpinButton) 178 appendChildAndSetId(shadowRoot, SpinButtonElement::create(document), spinButtonId()); 179 } 180 181 HTMLElement* TextFieldInputType::getShadowElementById(const AtomicString& id) const 182 { 183 if (!element()->shadowRoot()) 184 return 0; 185 Element* shadow = element()->shadowRoot()->getElementById(id); 186 return shadow ? static_cast<HTMLElement*>(shadow) : 0; 187 } 188 189 HTMLElement* TextFieldInputType::innerTextElement() const 190 { 191 return getShadowElementById(innerTextId()); 192 } 193 194 HTMLElement* TextFieldInputType::innerSpinButtonElement() const 195 { 196 return getShadowElementById(spinButtonId()); 197 } 198 199 #if ENABLE(INPUT_SPEECH) 200 HTMLElement* TextFieldInputType::speechButtonElement() const 201 { 202 return getShadowElementById(speechButtonId()); 203 } 204 #endif 177 205 178 206 bool TextFieldInputType::shouldUseInputMethod() const -
trunk/Source/WebCore/html/TextFieldInputType.h
r87881 r87980 36 36 namespace WebCore { 37 37 38 class ContainerNode; 39 38 40 // The class represents types of which UI contain text fields. 39 41 // It supports not only the types for BaseTextInputType but also type=number. … … 46 48 void handleWheelEventForSpinButton(WheelEvent*); 47 49 48 virtual HTMLElement* innerTextElement() const { return m_innerText; }49 virtual HTMLElement* innerSpinButtonElement() const { return m_innerSpinButton; }50 virtual HTMLElement* innerTextElement() const; 51 virtual HTMLElement* innerSpinButtonElement() const; 50 52 #if ENABLE(INPUT_SPEECH) 51 virtual HTMLElement* speechButtonElement() const { return m_speechButton; }53 virtual HTMLElement* speechButtonElement() const; 52 54 #endif 53 55 54 56 protected: 57 const AtomicString& innerTextId() const; 58 #if ENABLE(INPUT_SPEECH) 59 const AtomicString& speechButtonId() const; 60 #endif 61 static void appendChildAndSetId(ContainerNode*, PassRefPtr<HTMLElement>, const AtomicString&); 55 62 virtual void createShadowSubtree(); 56 virtual void destroyShadowSubtree(); 57 void setInnerTextElement(HTMLElement* element) { m_innerText = element; } 58 #if ENABLE(INPUT_SPEECH) 59 void setSpeechButtonElement(HTMLElement* element) { m_speechButton = element; } 60 #endif 63 HTMLElement* getShadowElementById(const AtomicString&) const; 61 64 62 65 private: … … 70 73 virtual String sanitizeValue(const String&); 71 74 virtual bool shouldRespectListAttribute(); 72 73 HTMLElement* m_innerText;74 HTMLElement* m_innerSpinButton;75 #if ENABLE(INPUT_SPEECH)76 HTMLElement* m_speechButton;77 #endif78 75 }; 79 76 -
trunk/Source/WebCore/html/shadow/TextControlInnerElements.cpp
r87881 r87980 64 64 } 65 65 66 PassRefPtr<Element> TextControlInnerElement::cloneElementWithoutAttributesAndChildren() const 67 { 68 return create(document()); 69 } 70 66 71 // ---------------------------- 67 72 … … 108 113 RenderTextControl* parentRenderer = toRenderTextControl(shadowAncestorNode()->renderer()); 109 114 return parentRenderer->createInnerTextStyle(parentRenderer->style()); 115 } 116 117 PassRefPtr<Element> TextControlInnerTextElement::cloneElementWithoutAttributesAndChildren() const 118 { 119 return create(document()); 110 120 } 111 121 … … 159 169 } 160 170 171 PassRefPtr<Element> SearchFieldResultsButtonElement::cloneElementWithoutAttributesAndChildren() const 172 { 173 return create(document()); 174 } 175 161 176 // ---------------------------- 162 177 … … 220 235 if (!event->defaultHandled()) 221 236 HTMLDivElement::defaultEventHandler(event); 237 } 238 239 PassRefPtr<Element> SearchFieldCancelButtonElement::cloneElementWithoutAttributesAndChildren() const 240 { 241 return create(document()); 222 242 } 223 243 … … 358 378 } 359 379 380 PassRefPtr<Element> SpinButtonElement::cloneElementWithoutAttributesAndChildren() const 381 { 382 return create(document()); 383 } 360 384 361 385 // ---------------------------- … … 526 550 } 527 551 552 PassRefPtr<Element> InputFieldSpeechButtonElement::cloneElementWithoutAttributesAndChildren() const 553 { 554 return create(document()); 555 } 556 528 557 #endif // ENABLE(INPUT_SPEECH) 529 558 -
trunk/Source/WebCore/html/shadow/TextControlInnerElements.h
r87881 r87980 47 47 private: 48 48 virtual bool isMouseFocusable() const { return false; } 49 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 49 50 }; 50 51 … … 60 61 virtual PassRefPtr<RenderStyle> styleForRenderer(); 61 62 virtual bool isMouseFocusable() const { return false; } 63 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 62 64 }; 63 65 … … 72 74 virtual const AtomicString& shadowPseudoId() const; 73 75 virtual bool isMouseFocusable() const { return false; } 76 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 74 77 }; 75 78 … … 85 88 virtual void detach(); 86 89 virtual bool isMouseFocusable() const { return false; } 90 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 87 91 88 92 bool m_capturing; … … 114 118 virtual void setHovered(bool = true); 115 119 virtual bool isMouseFocusable() const { return false; } 120 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 116 121 117 122 bool m_capturing; … … 153 158 virtual bool isMouseFocusable() const { return false; } 154 159 virtual void attach(); 160 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 155 161 156 162 bool m_capturing;
Note:
See TracChangeset
for help on using the changeset viewer.