/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #pragma once #include "HTMLFormControlElementWithState.h" namespace WebCore { class Position; class RenderTextControl; class TextControlInnerTextElement; class VisiblePosition; enum class AutoFillButtonType : uint8_t { None, Credentials, Contacts }; enum TextFieldSelectionDirection { SelectionHasNoDirection, SelectionHasForwardDirection, SelectionHasBackwardDirection }; enum TextFieldEventBehavior { DispatchNoEvent, DispatchChangeEvent, DispatchInputAndChangeEvent }; class HTMLTextFormControlElement : public HTMLFormControlElementWithState { public: // Common flag for HTMLInputElement::tooLong() / tooShort() and HTMLTextAreaElement::tooLong() / tooShort(). enum NeedsToCheckDirtyFlag {CheckDirtyFlag, IgnoreDirtyFlag}; virtual ~HTMLTextFormControlElement(); void didEditInnerTextValue(); void forwardEvent(Event&); int maxLength() const { return m_maxLength; } WEBCORE_EXPORT ExceptionOr setMaxLength(int); int minLength() const { return m_minLength; } ExceptionOr setMinLength(int); InsertionNotificationRequest insertedInto(ContainerNode&) override; // The derived class should return true if placeholder processing is needed. bool isPlaceholderVisible() const { return m_isPlaceholderVisible; } virtual bool supportsPlaceholder() const = 0; String strippedPlaceholder() const; virtual HTMLElement* placeholderElement() const = 0; void updatePlaceholderVisibility(); int indexForVisiblePosition(const VisiblePosition&) const; WEBCORE_EXPORT VisiblePosition visiblePositionForIndex(int index) const; WEBCORE_EXPORT int selectionStart() const; WEBCORE_EXPORT int selectionEnd() const; WEBCORE_EXPORT const AtomicString& selectionDirection() const; WEBCORE_EXPORT void setSelectionStart(int); WEBCORE_EXPORT void setSelectionEnd(int); WEBCORE_EXPORT void setSelectionDirection(const String&); WEBCORE_EXPORT void select(const AXTextStateChangeIntent& = AXTextStateChangeIntent()); WEBCORE_EXPORT virtual ExceptionOr setRangeText(const String& replacement); WEBCORE_EXPORT virtual ExceptionOr setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode); void setSelectionRange(int start, int end, const String& direction, const AXTextStateChangeIntent& = AXTextStateChangeIntent()); WEBCORE_EXPORT void setSelectionRange(int start, int end, TextFieldSelectionDirection = SelectionHasNoDirection, const AXTextStateChangeIntent& = AXTextStateChangeIntent()); RefPtr selection() const; String selectedText() const; void dispatchFormControlChangeEvent() final; virtual String value() const = 0; virtual TextControlInnerTextElement* innerTextElement() const = 0; virtual RenderStyle createInnerTextStyle(const RenderStyle&) const = 0; void selectionChanged(bool shouldFireSelectEvent); WEBCORE_EXPORT bool lastChangeWasUserEdit() const; void setInnerTextValue(const String&); String innerTextValue() const; String directionForFormData() const; void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; } #if PLATFORM(IOS) WEBCORE_EXPORT void hidePlaceholder(); WEBCORE_EXPORT void showPlaceholderIfNecessary(); #endif protected: HTMLTextFormControlElement(const QualifiedName&, Document&, HTMLFormElement*); bool isPlaceholderEmpty() const; virtual void updatePlaceholderText() = 0; void parseAttribute(const QualifiedName&, const AtomicString&) override; void disabledStateChanged() override; void readOnlyAttributeChanged() override; void updateInnerTextElementEditability(); void cacheSelection(int start, int end, TextFieldSelectionDirection direction) { m_cachedSelectionStart = start; m_cachedSelectionEnd = end; m_cachedSelectionDirection = direction; } void restoreCachedSelection(const AXTextStateChangeIntent& = AXTextStateChangeIntent()); bool hasCachedSelection() const { return m_cachedSelectionStart >= 0; } virtual void subtreeHasChanged() = 0; void setLastChangeWasNotUserEdit() { m_lastChangeWasUserEdit = false; } String valueWithHardLineBreaks() const; void adjustInnerTextStyle(const RenderStyle& parentStyle, RenderStyle& textBlockStyle) const; void internalSetMaxLength(int maxLength) { m_maxLength = maxLength; } void internalSetMinLength(int minLength) { m_minLength = minLength; } private: TextFieldSelectionDirection cachedSelectionDirection() const { return static_cast(m_cachedSelectionDirection); } int computeSelectionStart() const; int computeSelectionEnd() const; TextFieldSelectionDirection computeSelectionDirection() const; void dispatchFocusEvent(RefPtr&& oldFocusedElement, FocusDirection) final; void dispatchBlurEvent(RefPtr&& newFocusedElement) final; bool childShouldCreateRenderer(const Node&) const override; unsigned indexForPosition(const Position&) const; // Returns true if user-editable value is empty. Used to check placeholder visibility. virtual bool isEmptyValue() const = 0; // Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent(). virtual void handleFocusEvent(Node* /* oldFocusedNode */, FocusDirection) { } // Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent(). virtual void handleBlurEvent() { } bool placeholderShouldBeVisible() const; unsigned m_cachedSelectionDirection : 2; unsigned m_lastChangeWasUserEdit : 1; unsigned m_isPlaceholderVisible : 1; String m_textAsOfLastFormControlChangeEvent; int m_cachedSelectionStart; int m_cachedSelectionEnd; int m_maxLength { -1 }; int m_minLength { -1 }; }; HTMLTextFormControlElement* enclosingTextFormControl(const Position&); } // namespace WebCore SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLTextFormControlElement) static bool isType(const WebCore::Element& element) { return element.isTextFormControl(); } static bool isType(const WebCore::Node& node) { return is(node) && isType(downcast(node)); } SPECIALIZE_TYPE_TRAITS_END()