diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/WebCore/html/HTMLTextFormControlElement.cpp | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/WebCore/html/HTMLTextFormControlElement.cpp')
-rw-r--r-- | Source/WebCore/html/HTMLTextFormControlElement.cpp | 360 |
1 files changed, 219 insertions, 141 deletions
diff --git a/Source/WebCore/html/HTMLTextFormControlElement.cpp b/Source/WebCore/html/HTMLTextFormControlElement.cpp index af222e4ac..149f9dbf9 100644 --- a/Source/WebCore/html/HTMLTextFormControlElement.cpp +++ b/Source/WebCore/html/HTMLTextFormControlElement.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2014 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or @@ -26,12 +26,10 @@ #include "HTMLTextFormControlElement.h" #include "AXObjectCache.h" -#include "Attribute.h" #include "ChromeClient.h" #include "Document.h" #include "Event.h" #include "EventNames.h" -#include "FeatureObserver.h" #include "Frame.h" #include "FrameSelection.h" #include "HTMLBRElement.h" @@ -39,6 +37,7 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" #include "NodeTraversal.h" +#include "Page.h" #include "RenderBlockFlow.h" #include "RenderTextControlSingleLine.h" #include "RenderTheme.h" @@ -52,12 +51,15 @@ namespace WebCore { using namespace HTMLNames; +static Position positionForIndex(TextControlInnerTextElement*, unsigned); + HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form) : HTMLFormControlElementWithState(tagName, document, form) - , m_lastChangeWasUserEdit(false) , m_cachedSelectionStart(-1) , m_cachedSelectionEnd(-1) , m_cachedSelectionDirection(SelectionHasNoDirection) + , m_lastChangeWasUserEdit(false) + , m_isPlaceholderVisible(false) { } @@ -76,39 +78,37 @@ bool HTMLTextFormControlElement::childShouldCreateRenderer(const Node& child) co Node::InsertionNotificationRequest HTMLTextFormControlElement::insertedInto(ContainerNode& insertionPoint) { - HTMLFormControlElementWithState::insertedInto(insertionPoint); + InsertionNotificationRequest insertionNotificationRequest = HTMLFormControlElementWithState::insertedInto(insertionPoint); if (!insertionPoint.inDocument()) - return InsertionDone; + return insertionNotificationRequest; String initialValue = value(); setTextAsOfLastFormControlChangeEvent(initialValue.isNull() ? emptyString() : initialValue); - return InsertionDone; + return insertionNotificationRequest; } -void HTMLTextFormControlElement::dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection direction) +void HTMLTextFormControlElement::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection direction) { if (supportsPlaceholder()) - updatePlaceholderVisibility(false); + updatePlaceholderVisibility(); handleFocusEvent(oldFocusedElement.get(), direction); - HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction); + HTMLFormControlElementWithState::dispatchFocusEvent(WTFMove(oldFocusedElement), direction); } -void HTMLTextFormControlElement::dispatchBlurEvent(PassRefPtr<Element> newFocusedElement) +void HTMLTextFormControlElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement) { if (supportsPlaceholder()) - updatePlaceholderVisibility(false); + updatePlaceholderVisibility(); handleBlurEvent(); - HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); + HTMLFormControlElementWithState::dispatchBlurEvent(WTFMove(newFocusedElement)); } -void HTMLTextFormControlElement::defaultEventHandler(Event* event) +void HTMLTextFormControlElement::didEditInnerTextValue() { - if (event->type() == eventNames().webkitEditableContentChangedEvent && renderer() && renderer()->isTextControl()) { - m_lastChangeWasUserEdit = true; - subtreeHasChanged(); + if (!isTextFormControl()) return; - } - HTMLFormControlElementWithState::defaultEventHandler(event); + m_lastChangeWasUserEdit = true; + subtreeHasChanged(); } void HTMLTextFormControlElement::forwardEvent(Event* event) @@ -148,24 +148,23 @@ bool HTMLTextFormControlElement::isPlaceholderEmpty() const bool HTMLTextFormControlElement::placeholderShouldBeVisible() const { - return supportsPlaceholder() - && isEmptyValue() - && isEmptySuggestedValue() - && !isPlaceholderEmpty() - && (document().focusedElement() != this || (renderer() && renderer()->theme().shouldShowPlaceholderWhenFocused())) - && (!renderer() || renderer()->style().visibility() == VISIBLE); + // This function is used by the style resolver to match the :placeholder-shown pseudo class. + // Since it is used for styling, it must not use any value depending on the style. + return supportsPlaceholder() && isEmptyValue() && !isPlaceholderEmpty(); } -void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged) +void HTMLTextFormControlElement::updatePlaceholderVisibility() { - if (!supportsPlaceholder()) - return; - if (!placeholderElement() || placeholderValueChanged) - updatePlaceholderText(); - HTMLElement* placeholder = placeholderElement(); - if (!placeholder) + bool placeHolderWasVisible = m_isPlaceholderVisible; + m_isPlaceholderVisible = placeholderShouldBeVisible(); + + if (placeHolderWasVisible == m_isPlaceholderVisible) return; - placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden); + + setNeedsStyleRecalc(); + + if (HTMLElement* placeholder = placeholderElement()) + placeholder->setInlineStyleProperty(CSSPropertyDisplay, m_isPlaceholderVisible ? CSSValueBlock : CSSValueNone, true); } void HTMLTextFormControlElement::setSelectionStart(int start) @@ -183,15 +182,15 @@ void HTMLTextFormControlElement::setSelectionDirection(const String& direction) setSelectionRange(selectionStart(), selectionEnd(), direction); } -void HTMLTextFormControlElement::select() +void HTMLTextFormControlElement::select(const AXTextStateChangeIntent& intent) { // FIXME: We should abstract the selection behavior into an EditingBehavior function instead // of hardcoding the behavior using a macro define. #if PLATFORM(IOS) // We don't want to select all the text on iOS. Instead use the standard textfield behavior of going to the end of the line. - setSelectionRange(std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), SelectionHasForwardDirection); + setSelectionRange(std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), SelectionHasForwardDirection, intent); #else - setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection); + setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection, intent); #endif } @@ -211,11 +210,6 @@ void HTMLTextFormControlElement::dispatchFormControlChangeEvent() setChangedSinceLastFormControlChangeEvent(false); } -static inline bool hasVisibleTextArea(RenderElement& textControl, TextControlInnerTextElement* innerText) -{ - return textControl.style().visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height(); -} - void HTMLTextFormControlElement::setRangeText(const String& replacement, ExceptionCode& ec) { setRangeText(replacement, selectionStart(), selectionEnd(), String(), ec); @@ -250,12 +244,12 @@ void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigne subtreeHasChanged(); - if (equalIgnoringCase(selectionMode, "select")) { + if (equalLettersIgnoringASCIICase(selectionMode, "select")) { newSelectionStart = start; newSelectionEnd = start + replacementLength; - } else if (equalIgnoringCase(selectionMode, "start")) + } else if (equalLettersIgnoringASCIICase(selectionMode, "start")) newSelectionStart = newSelectionEnd = start; - else if (equalIgnoringCase(selectionMode, "end")) + else if (equalLettersIgnoringASCIICase(selectionMode, "end")) newSelectionStart = newSelectionEnd = start + replacementLength; else { // Default is "preserve". @@ -275,7 +269,7 @@ void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigne setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection); } -void HTMLTextFormControlElement::setSelectionRange(int start, int end, const String& directionString) +void HTMLTextFormControlElement::setSelectionRange(int start, int end, const String& directionString, const AXTextStateChangeIntent& intent) { TextFieldSelectionDirection direction = SelectionHasNoDirection; if (directionString == "forward") @@ -283,60 +277,61 @@ void HTMLTextFormControlElement::setSelectionRange(int start, int end, const Str else if (directionString == "backward") direction = SelectionHasBackwardDirection; - return setSelectionRange(start, end, direction); + return setSelectionRange(start, end, direction, intent); } -void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction) +void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction, const AXTextStateChangeIntent& intent) { - document().updateLayoutIgnorePendingStylesheets(); - - if (!renderer() || !renderer()->isTextControl()) + if (!isTextFormControl()) return; end = std::max(end, 0); start = std::min(std::max(start, 0), end); - if (!hasVisibleTextArea(*renderer(), innerTextElement())) { - cacheSelection(start, end, direction); - return; + TextControlInnerTextElement* innerText = innerTextElement(); + bool hasFocus = document().focusedElement() == this; + if (!hasFocus && innerText) { + // FIXME: Removing this synchronous layout requires fixing <https://webkit.org/b/128797> + document().updateLayoutIgnorePendingStylesheets(); + if (RenderElement* rendererTextControl = renderer()) { + if (rendererTextControl->style().visibility() == HIDDEN || !innerText->renderBox()->height()) { + cacheSelection(start, end, direction); + return; + } + } } - VisiblePosition startPosition = visiblePositionForIndex(start); - VisiblePosition endPosition; + + Position startPosition = positionForIndex(innerText, start); + Position endPosition; if (start == end) endPosition = startPosition; - else - endPosition = visiblePositionForIndex(end); - -#if !PLATFORM(IOS) - // startPosition and endPosition can be null position for example when - // "-webkit-user-select: none" style attribute is specified. - if (startPosition.isNotNull() && endPosition.isNotNull()) { - ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this - && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this); + else { + if (direction == SelectionHasBackwardDirection) { + endPosition = startPosition; + startPosition = positionForIndex(innerText, end); + } else + endPosition = positionForIndex(innerText, end); } -#endif - VisibleSelection newSelection; - if (direction == SelectionHasBackwardDirection) - newSelection = VisibleSelection(endPosition, startPosition); - else - newSelection = VisibleSelection(startPosition, endPosition); - newSelection.setIsDirectional(direction != SelectionHasNoDirection); if (Frame* frame = document().frame()) - frame->selection().setSelection(newSelection); + frame->selection().moveWithoutValidationTo(startPosition, endPosition, direction != SelectionHasNoDirection, !hasFocus, intent); } -int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const +int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& position) const { - if (enclosingTextFormControl(pos.deepEquivalent()) != this) + TextControlInnerTextElement* innerText = innerTextElement(); + if (!innerText || !innerText->contains(position.deepEquivalent().anchorNode())) return 0; - bool forSelectionPreservation = false; - return WebCore::indexForVisiblePosition(innerTextElement(), pos, forSelectionPreservation); + unsigned index = indexForPosition(position.deepEquivalent()); + ASSERT(VisiblePosition(positionForIndex(innerTextElement(), index)) == position); + return index; } VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const { - return visiblePositionForIndexUsingCharacterIterator(innerTextElement(), index); + VisiblePosition position = positionForIndex(innerTextElement(), index); + ASSERT(indexForVisiblePosition(position) == index); + return position; } int HTMLTextFormControlElement::selectionStart() const @@ -356,7 +351,7 @@ int HTMLTextFormControlElement::computeSelectionStart() const if (!frame) return 0; - return indexForVisiblePosition(frame->selection().start()); + return indexForPosition(frame->selection().selection().start()); } int HTMLTextFormControlElement::selectionEnd() const @@ -375,14 +370,14 @@ int HTMLTextFormControlElement::computeSelectionEnd() const if (!frame) return 0; - return indexForVisiblePosition(frame->selection().end()); + return indexForPosition(frame->selection().selection().end()); } static const AtomicString& directionString(TextFieldSelectionDirection direction) { - DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, forward, ("forward", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, backward, ("backward", AtomicString::ConstructFromLiteral)); + static NeverDestroyed<const AtomicString> none("none", AtomicString::ConstructFromLiteral); + static NeverDestroyed<const AtomicString> forward("forward", AtomicString::ConstructFromLiteral); + static NeverDestroyed<const AtomicString> backward("backward", AtomicString::ConstructFromLiteral); switch (direction) { case SelectionHasNoDirection: @@ -402,7 +397,7 @@ const AtomicString& HTMLTextFormControlElement::selectionDirection() const if (!isTextFormControl()) return directionString(SelectionHasNoDirection); if (document().focusedElement() != this && hasCachedSelection()) - return directionString(m_cachedSelectionDirection); + return directionString(cachedSelectionDirection()); return directionString(computeSelectionDirection()); } @@ -425,14 +420,14 @@ static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& offsetInContainer = offset; } else { containerNode = node->parentNode(); - offsetInContainer = node->nodeIndex() + offset; + offsetInContainer = node->computeNodeIndex() + offset; } } PassRefPtr<Range> HTMLTextFormControlElement::selection() const { if (!renderer() || !isTextFormControl() || !hasCachedSelection()) - return 0; + return nullptr; int start = m_cachedSelectionStart; int end = m_cachedSelectionEnd; @@ -440,15 +435,15 @@ PassRefPtr<Range> HTMLTextFormControlElement::selection() const ASSERT(start <= end); TextControlInnerTextElement* innerText = innerTextElement(); if (!innerText) - return 0; + return nullptr; if (!innerText->firstChild()) return Range::create(document(), innerText, 0, innerText, 0); int offset = 0; - Node* startNode = 0; - Node* endNode = 0; - for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) { + Node* startNode = nullptr; + Node* endNode = nullptr; + for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) { ASSERT(!node->firstChild()); ASSERT(node->isTextNode() || node->hasTagName(brTag)); int length = node->isTextNode() ? lastOffsetInNode(node) : 1; @@ -465,17 +460,17 @@ PassRefPtr<Range> HTMLTextFormControlElement::selection() const } if (!startNode || !endNode) - return 0; + return nullptr; return Range::create(document(), startNode, start, endNode, end); } -void HTMLTextFormControlElement::restoreCachedSelection() +void HTMLTextFormControlElement::restoreCachedSelection(const AXTextStateChangeIntent& intent) { - setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection); + setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, cachedSelectionDirection(), intent); } -void HTMLTextFormControlElement::selectionChanged(bool userTriggered) +void HTMLTextFormControlElement::selectionChanged(bool shouldFireSelectEvent) { if (!isTextFormControl()) return; @@ -483,22 +478,38 @@ void HTMLTextFormControlElement::selectionChanged(bool userTriggered) // FIXME: Don't re-compute selection start and end if this function was called inside setSelectionRange. // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection()); - - if (Frame* frame = document().frame()) { - if (frame->selection().isRange() && userTriggered) - dispatchEvent(Event::create(eventNames().selectEvent, true, false)); - } + + if (shouldFireSelectEvent && m_cachedSelectionStart != m_cachedSelectionEnd) + dispatchEvent(Event::create(eventNames().selectEvent, true, false)); } void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (name == placeholderAttr) { - updatePlaceholderVisibility(true); - FeatureObserver::observe(&document(), FeatureObserver::PlaceholderAttribute); + updatePlaceholderText(); + updatePlaceholderVisibility(); } else HTMLFormControlElementWithState::parseAttribute(name, value); } +void HTMLTextFormControlElement::disabledStateChanged() +{ + HTMLFormControlElementWithState::disabledStateChanged(); + updateInnerTextElementEditability(); +} + +void HTMLTextFormControlElement::readOnlyAttributeChanged() +{ + HTMLFormControlElementWithState::disabledAttributeChanged(); + updateInnerTextElementEditability(); +} + +void HTMLTextFormControlElement::updateInnerTextElementEditability() +{ + if (TextControlInnerTextElement* innerText = innerTextElement()) + innerText->setAttribute(contenteditableAttr, isDisabledOrReadOnly() ? "false" : "plaintext-only"); +} + bool HTMLTextFormControlElement::lastChangeWasUserEdit() const { if (!isTextFormControl()) @@ -506,70 +517,136 @@ bool HTMLTextFormControlElement::lastChangeWasUserEdit() const return m_lastChangeWasUserEdit; } +static void stripTrailingNewline(StringBuilder& result) +{ + // Remove one trailing newline; there's always one that's collapsed out by rendering. + size_t size = result.length(); + if (size && result[size - 1] == newlineCharacter) + result.resize(size - 1); +} + +static String innerTextValueFrom(TextControlInnerTextElement& innerText) +{ + StringBuilder result; + for (Node* node = innerText.firstChild(); node; node = NodeTraversal::next(*node, &innerText)) { + if (is<HTMLBRElement>(*node)) + result.append(newlineCharacter); + else if (is<Text>(*node)) + result.append(downcast<Text>(*node).data()); + } + stripTrailingNewline(result); + return result.toString(); +} + void HTMLTextFormControlElement::setInnerTextValue(const String& value) { - if (!isTextFormControl()) + TextControlInnerTextElement* innerText = innerTextElement(); + if (!innerText) return; - bool textIsChanged = value != innerTextValue(); - if (textIsChanged || !innerTextElement()->hasChildNodes()) { + ASSERT(isTextFormControl()); + String previousValue = innerTextValueFrom(*innerText); + bool textIsChanged = value != previousValue; + if (textIsChanged || !innerText->hasChildNodes()) { +#if HAVE(ACCESSIBILITY) && !PLATFORM(COCOA) if (textIsChanged && renderer()) { if (AXObjectCache* cache = document().existingAXObjectCache()) cache->postNotification(this, AXObjectCache::AXValueChanged, TargetObservableParent); } - innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION); +#endif + innerText->setInnerText(value, ASSERT_NO_EXCEPTION); if (value.endsWith('\n') || value.endsWith('\r')) - innerTextElement()->appendChild(HTMLBRElement::create(document()), ASSERT_NO_EXCEPTION); + innerText->appendChild(HTMLBRElement::create(document()), ASSERT_NO_EXCEPTION); + +#if HAVE(ACCESSIBILITY) && PLATFORM(COCOA) + if (textIsChanged && renderer()) { + if (AXObjectCache* cache = document().existingAXObjectCache()) + cache->postTextReplacementNotification(this, AXTextEditTypeDelete, previousValue, AXTextEditTypeInsert, value, VisiblePosition(Position(this, Position::PositionIsBeforeAnchor))); + } +#endif } setFormControlValueMatchesRenderer(true); } -static String finishText(StringBuilder& result) +String HTMLTextFormControlElement::innerTextValue() const { - // Remove one trailing newline; there's always one that's collapsed out by rendering. - size_t size = result.length(); - if (size && result[size - 1] == '\n') - result.resize(--size); - return result.toString(); + TextControlInnerTextElement* innerText = innerTextElement(); + return innerText ? innerTextValueFrom(*innerText) : emptyString(); +} + +static Position positionForIndex(TextControlInnerTextElement* innerText, unsigned index) +{ + unsigned remainingCharactersToMoveForward = index; + Node* lastBrOrText = innerText; + for (Node* node = innerText; node; node = NodeTraversal::next(*node, innerText)) { + if (node->hasTagName(brTag)) { + if (!remainingCharactersToMoveForward) + return positionBeforeNode(node); + remainingCharactersToMoveForward--; + lastBrOrText = node; + } else if (is<Text>(*node)) { + Text& text = downcast<Text>(*node); + if (remainingCharactersToMoveForward < text.length()) + return Position(&text, remainingCharactersToMoveForward); + remainingCharactersToMoveForward -= text.length(); + lastBrOrText = node; + } + } + return lastPositionInOrAfterNode(lastBrOrText); } -String HTMLTextFormControlElement::innerTextValue() const +unsigned HTMLTextFormControlElement::indexForPosition(const Position& passedPosition) const { - if (!isTextFormControl()) - return emptyString(); - TextControlInnerTextElement* innerText = innerTextElement(); - if (!innerText) - return emptyString(); + if (!innerText || !innerText->contains(passedPosition.anchorNode()) || passedPosition.isNull()) + return 0; - StringBuilder result; - for (Node* node = innerText; node; node = NodeTraversal::next(node, innerText)) { - if (node->hasTagName(brTag)) - result.append(newlineCharacter); - else if (node->isTextNode()) - result.append(toText(node)->data()); + if (positionBeforeNode(innerText) == passedPosition) + return 0; + + unsigned index = 0; + Node* startNode = passedPosition.computeNodeBeforePosition(); + if (!startNode) + startNode = passedPosition.containerNode(); + ASSERT(startNode); + ASSERT(innerText->contains(startNode)); + + for (Node* node = startNode; node; node = NodeTraversal::previous(*node, innerText)) { + if (is<Text>(*node)) { + unsigned length = downcast<Text>(*node).length(); + if (node == passedPosition.containerNode()) + index += std::min<unsigned>(length, passedPosition.offsetInContainerNode()); + else + index += length; + } else if (is<HTMLBRElement>(*node)) + ++index; } - return finishText(result); + + unsigned length = innerTextValue().length(); + index = std::min(index, length); // FIXME: We shouldn't have to call innerTextValue() just to ignore the last LF. See finishText. +#ifndef ASSERT_DISABLED + VisiblePosition visiblePosition = passedPosition; + unsigned indexComputedByVisiblePosition = 0; + if (visiblePosition.isNotNull()) + indexComputedByVisiblePosition = WebCore::indexForVisiblePosition(innerText, visiblePosition, false /* forSelectionPreservation */); + ASSERT(index == indexComputedByVisiblePosition); +#endif + return index; } #if PLATFORM(IOS) void HTMLTextFormControlElement::hidePlaceholder() { - if (!supportsPlaceholder()) - return; - HTMLElement* placeholder = placeholderElement(); - if (!placeholder) { - updatePlaceholderText(); - return; - } - placeholder->setInlineStyleProperty(CSSPropertyVisibility, ASCIILiteral("hidden")); + if (HTMLElement* placeholder = placeholderElement()) + placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden, true); } void HTMLTextFormControlElement::showPlaceholderIfNecessary() { - updatePlaceholderVisibility(false); + if (HTMLElement* placeholder = placeholderElement()) + placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueVisible, true); } #endif @@ -614,11 +691,11 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const getNextSoftBreak(line, breakNode, breakOffset); StringBuilder result; - for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) { - if (node->hasTagName(brTag)) + for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) { + if (is<HTMLBRElement>(*node)) result.append(newlineCharacter); - else if (node->isTextNode()) { - String data = toText(node)->data(); + else if (is<Text>(*node)) { + String data = downcast<Text>(*node).data(); unsigned length = data.length(); unsigned position = 0; while (breakNode == node && breakOffset <= length) { @@ -634,7 +711,8 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const while (breakNode == node) getNextSoftBreak(line, breakNode, breakOffset); } - return finishText(result); + stripTrailingNewline(result); + return result.toString(); } HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) @@ -647,7 +725,7 @@ HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) if (!container) return nullptr; Element* ancestor = container->shadowHost(); - return ancestor && isHTMLTextFormControlElement(*ancestor) ? toHTMLTextFormControlElement(ancestor) : nullptr; + return ancestor && is<HTMLTextFormControlElement>(*ancestor) ? downcast<HTMLTextFormControlElement>(ancestor) : nullptr; } static const Element* parentHTMLElement(const Element* element) @@ -667,10 +745,10 @@ String HTMLTextFormControlElement::directionForFormData() const if (dirAttributeValue.isNull()) continue; - if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr")) + if (equalLettersIgnoringASCIICase(dirAttributeValue, "rtl") || equalLettersIgnoringASCIICase(dirAttributeValue, "ltr")) return dirAttributeValue; - if (equalIgnoringCase(dirAttributeValue, "auto")) { + if (equalLettersIgnoringASCIICase(dirAttributeValue, "auto")) { bool isAuto; TextDirection textDirection = static_cast<const HTMLElement*>(element)->directionalityIfhasDirAutoAttribute(isAuto); return textDirection == RTL ? "rtl" : "ltr"; |