1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_HTMLTextAreaElement_h
#define mozilla_dom_HTMLTextAreaElement_h
#include "mozilla/Attributes.h"
#include "mozilla/TextControlElement.h"
#include "mozilla/TextControlState.h"
#include "mozilla/TextEditor.h"
#include "mozilla/dom/ConstraintValidation.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLInputElementBinding.h"
#include "nsCOMPtr.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsIControllers.h"
#include "nsStubMutationObserver.h"
class nsIControllers;
class nsPresContext;
namespace mozilla {
class EventChainPostVisitor;
class EventChainPreVisitor;
class PresState;
namespace dom {
class FormData;
class HTMLTextAreaElement final : public TextControlElement,
public nsStubMutationObserver,
public ConstraintValidation {
public:
using ConstraintValidation::GetValidationMessage;
using ValueSetterOption = TextControlState::ValueSetterOption;
using ValueSetterOptions = TextControlState::ValueSetterOptions;
explicit HTMLTextAreaElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser = NOT_FROM_PARSER);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLTextAreaElement, textarea)
int32_t TabIndexDefault() override;
// Element
bool IsInteractiveHTMLContent() const override { return true; }
// nsGenericHTMLElement
bool IsDisabledForEvents(WidgetEvent* aEvent) override;
// nsGenericHTMLFormElement
void SaveState() override;
// FIXME: Shouldn't be a CAN_RUN_SCRIPT_BOUNDARY probably?
MOZ_CAN_RUN_SCRIPT_BOUNDARY bool RestoreState(PresState*) override;
// nsIFormControl
MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD Reset() override;
NS_IMETHOD SubmitNamesValues(FormData* aFormData) override;
void FieldSetDisabledChanged(bool aNotify) override;
void SetLastValueChangeWasInteractive(bool);
// TextControlElement
bool IsSingleLineTextControlOrTextArea() const override { return true; }
void SetValueChanged(bool aValueChanged) override;
bool IsSingleLineTextControl() const override;
bool IsTextArea() const override;
bool IsPasswordTextControl() const override;
Maybe<int32_t> GetCols() override;
int32_t GetWrapCols() override;
int32_t GetRows() override;
void GetDefaultValueFromContent(nsAString& aValue, bool aForDisplay) override;
bool ValueChanged() const override;
void GetTextEditorValue(nsAString& aValue) const override;
MOZ_CAN_RUN_SCRIPT TextEditor* GetTextEditor() override;
TextEditor* GetExtantTextEditor() const override;
nsISelectionController* GetSelectionController() override;
nsFrameSelection* GetIndependentFrameSelection() const override;
TextControlState* GetTextControlState() const override { return mState; }
nsresult BindToFrame(nsTextControlFrame* aFrame) override;
MOZ_CAN_RUN_SCRIPT void UnbindFromFrame(nsTextControlFrame* aFrame) override;
MOZ_CAN_RUN_SCRIPT nsresult CreateEditor() override;
void SetPreviewValue(const nsAString& aValue) override;
void GetPreviewValue(nsAString& aValue) override;
void SetAutofillState(const nsAString& aState) override {
SetFormAutofillState(aState);
}
void GetAutofillState(nsAString& aState) override {
GetFormAutofillState(aState);
}
void EnablePreview() override;
bool IsPreviewEnabled() override;
void InitializeKeyboardEventListeners() override;
void UpdatePlaceholderShownState();
void OnValueChanged(ValueChangeKind, bool aNewValueEmpty,
const nsAString* aKnownNewValue) override;
void GetValueFromSetRangeText(nsAString& aValue) override;
MOZ_CAN_RUN_SCRIPT nsresult
SetValueFromSetRangeText(const nsAString& aValue) override;
bool HasCachedSelection() override;
// nsIContent
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
AttrModType aModType) const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
void DoneAddingChildren(bool aHaveNotified) override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult CopyInnerTo(Element* aDest);
/**
* Called when an attribute is about to be changed
*/
void BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement,
TextControlElement)
// nsIConstraintValidation
bool IsTooLong();
bool IsTooShort();
bool IsValueMissing() const;
void UpdateTooLongValidityState();
void UpdateTooShortValidityState();
void UpdateValueMissingValidityState();
void UpdateBarredFromConstraintValidation();
// ConstraintValidation
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidityStateType aType) override;
// Web IDL binding methods
void GetAutocomplete(nsAString& aValue);
void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) {
SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
}
void GetAutocompleteInfo(AutocompleteInfo& aInfo);
uint32_t Cols() { return GetColsOrDefault(); }
void SetCols(uint32_t aCols, ErrorResult& aError) {
uint32_t cols = aCols ? aCols : DEFAULT_COLS;
SetUnsignedIntAttr(nsGkAtoms::cols, cols, DEFAULT_COLS, aError);
}
void GetDirName(nsAString& aValue) {
GetHTMLAttr(nsGkAtoms::dirname, aValue);
}
void SetDirName(const nsAString& aValue, ErrorResult& aError) {
SetHTMLAttr(nsGkAtoms::dirname, aValue, aError);
}
bool Disabled() { return GetBoolAttr(nsGkAtoms::disabled); }
void SetDisabled(bool aDisabled, ErrorResult& aError) {
SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aError);
}
// nsGenericHTMLFormControlElementWithState::GetForm is fine
using nsGenericHTMLFormControlElementWithState::GetForm;
int32_t MaxLength() const { return GetIntAttr(nsGkAtoms::maxlength, -1); }
int32_t UsedMaxLength() const final { return MaxLength(); }
void SetMaxLength(int32_t aMaxLength, ErrorResult& aError) {
int32_t minLength = MinLength();
if (aMaxLength < 0 || (minLength >= 0 && aMaxLength < minLength)) {
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
} else {
SetHTMLIntAttr(nsGkAtoms::maxlength, aMaxLength, aError);
}
}
int32_t MinLength() const { return GetIntAttr(nsGkAtoms::minlength, -1); }
void SetMinLength(int32_t aMinLength, ErrorResult& aError) {
int32_t maxLength = MaxLength();
if (aMinLength < 0 || (maxLength >= 0 && aMinLength > maxLength)) {
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
} else {
SetHTMLIntAttr(nsGkAtoms::minlength, aMinLength, aError);
}
}
void GetName(nsAString& aName) { GetHTMLAttr(nsGkAtoms::name, aName); }
void SetName(const nsAString& aName, ErrorResult& aError) {
SetHTMLAttr(nsGkAtoms::name, aName, aError);
}
void GetPlaceholder(nsAString& aPlaceholder) {
GetHTMLAttr(nsGkAtoms::placeholder, aPlaceholder);
}
void SetPlaceholder(const nsAString& aPlaceholder, ErrorResult& aError) {
SetHTMLAttr(nsGkAtoms::placeholder, aPlaceholder, aError);
}
bool ReadOnly() { return GetBoolAttr(nsGkAtoms::readonly); }
void SetReadOnly(bool aReadOnly, ErrorResult& aError) {
SetHTMLBoolAttr(nsGkAtoms::readonly, aReadOnly, aError);
}
bool Required() const { return State().HasState(ElementState::REQUIRED); }
MOZ_CAN_RUN_SCRIPT void SetRangeText(const nsAString& aReplacement,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT void SetRangeText(const nsAString& aReplacement,
uint32_t aStart, uint32_t aEnd,
SelectionMode aSelectMode,
ErrorResult& aRv);
void SetRequired(bool aRequired, ErrorResult& aError) {
SetHTMLBoolAttr(nsGkAtoms::required, aRequired, aError);
}
uint32_t Rows() {
return GetUnsignedIntAttr(nsGkAtoms::rows, DEFAULT_ROWS_TEXTAREA);
}
void SetRows(uint32_t aRows, ErrorResult& aError) {
uint32_t rows = aRows ? aRows : DEFAULT_ROWS_TEXTAREA;
SetUnsignedIntAttr(nsGkAtoms::rows, rows, DEFAULT_ROWS_TEXTAREA, aError);
}
void GetWrap(nsAString& aWrap) { GetHTMLAttr(nsGkAtoms::wrap, aWrap); }
void SetWrap(const nsAString& aWrap, ErrorResult& aError) {
SetHTMLAttr(nsGkAtoms::wrap, aWrap, aError);
}
void GetType(nsAString& aType);
void GetDefaultValue(nsAString& aDefaultValue, ErrorResult& aError) const;
void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aError);
void GetValue(nsAString& aValue);
MOZ_CAN_RUN_SCRIPT void SetValue(const nsAString&, ErrorResult&);
uint32_t GetTextLength();
// Override SetCustomValidity so we update our state properly when it's called
// via bindings.
void SetCustomValidity(const nsAString& aError);
MOZ_CAN_RUN_SCRIPT void Select();
Nullable<uint32_t> GetSelectionStart(ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetSelectionStart(
const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError);
Nullable<uint32_t> GetSelectionEnd(ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetSelectionEnd(
const Nullable<uint32_t>& aSelectionEnd, ErrorResult& aError);
void GetSelectionDirection(nsAString& aDirection, ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetSelectionDirection(const nsAString& aDirection,
ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetSelectionRange(
uint32_t aSelectionStart, uint32_t aSelectionEnd,
const Optional<nsAString>& aDirecton, ErrorResult& aError);
nsIControllers* GetControllers(ErrorResult& aError);
nsIControllers* GetExtantControllers() const { return mControllers; }
// XPCOM adapter function widely used throughout code, leaving it as is.
nsresult GetControllers(nsIControllers** aResult);
MOZ_CAN_RUN_SCRIPT nsIEditor* GetEditorForBindings();
bool HasEditor() const {
MOZ_ASSERT(mState);
return !!mState->GetExtantTextEditor();
}
bool IsInputEventTarget() const { return true; }
MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetUserInput(
const nsAString& aValue, nsIPrincipal& aSubjectPrincipal);
protected:
MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual ~HTMLTextAreaElement();
// get rid of the compiler warning
using nsGenericHTMLFormControlElementWithState::IsSingleLineTextControl;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
void ResetIfUnchanged() {
if (!mValueChanged) {
Reset();
}
}
nsCOMPtr<nsIControllers> mControllers;
/** https://html.spec.whatwg.org/#user-interacted */
bool mUserInteracted = false;
/** Whether or not the value has changed since its default value was given. */
bool mValueChanged = false;
/** Whether or not the last change to the value was made interactively by the
* user. */
bool mLastValueChangeWasInteractive = false;
/** Whether or not we are already handling select event. */
bool mHandlingSelect = false;
/** Whether or not we are done adding children (always true if not
created by a parser */
bool mDoneAddingChildren;
/** Whether state restoration should be inhibited in DoneAddingChildren. */
bool mInhibitStateRestoration;
/** Whether our disabled state has changed from the default **/
bool mDisabledChanged = false;
bool mIsPreviewEnabled = false;
nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
nsContentUtils::AutocompleteAttrState mAutocompleteInfoState;
void FireChangeEventIfNeeded();
nsString mFocusedValue;
/** The state of the text editor (selection controller and the editor) **/
TextControlState* mState;
MOZ_CAN_RUN_SCRIPT void SelectAll();
/**
* Get the value, whether it is from the content or the frame.
* @param aValue the value [out]
*/
void GetValueInternal(nsAString& aValue) const;
/**
* Setting the value.
*
* @param aValue String to set.
* @param aOptions See TextControlState::ValueSetterOption.
*/
MOZ_CAN_RUN_SCRIPT nsresult
SetValueInternal(const nsAString& aValue, const ValueSetterOptions& aOptions);
/**
* Common method to call from the various mutation observer methods.
* aContent is a content node that's either the one that changed or its
* parent; we should only respond to the change if aContent is non-anonymous.
*/
void ContentChanged(nsIContent* aContent);
void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal, bool aNotify) override;
/**
* Get the mutable state of the element.
*/
bool IsMutable() const;
/**
* Returns whether the current value is the empty string.
*
* @return whether the current value is the empty string.
*/
bool IsValueEmpty() const {
return State().HasState(ElementState::VALUE_EMPTY);
}
/**
* A helper to get the current selection range. Will throw on the ErrorResult
* if we have no editor state.
*/
void GetSelectionRange(uint32_t* aSelectionStart, uint32_t* aSelectionEnd,
ErrorResult& aRv);
void SetUserInteracted(bool) final;
void UpdateValidityElementStates(bool aNotify);
private:
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace dom
} // namespace mozilla
#endif
|