HTMLOutputElement.cpp (5164B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/HTMLOutputElement.h" 8 9 #include "mozAutoDocUpdate.h" 10 #include "mozilla/dom/HTMLFormElement.h" 11 #include "mozilla/dom/HTMLOutputElementBinding.h" 12 #include "nsContentUtils.h" 13 #include "nsDOMTokenList.h" 14 15 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output) 16 17 namespace mozilla::dom { 18 19 HTMLOutputElement::HTMLOutputElement( 20 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 21 FromParser aFromParser) 22 : nsGenericHTMLFormControlElement(std::move(aNodeInfo), 23 FormControlType::Output), 24 mValueModeFlag(eModeDefault), 25 mIsDoneAddingChildren(!aFromParser) { 26 AddMutationObserver(this); 27 28 // <output> is always barred from constraint validation since it is not a 29 // submittable element. 30 SetBarredFromConstraintValidation(true); 31 } 32 33 HTMLOutputElement::~HTMLOutputElement() = default; 34 35 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLOutputElement, 36 nsGenericHTMLFormControlElement, mValidity, 37 mTokenList) 38 39 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLOutputElement, 40 nsGenericHTMLFormControlElement, 41 nsIMutationObserver, 42 nsIConstraintValidation) 43 44 NS_IMPL_ELEMENT_CLONE(HTMLOutputElement) 45 46 void HTMLOutputElement::SetCustomValidity(const nsAString& aError) { 47 ConstraintValidation::SetCustomValidity(aError); 48 } 49 50 NS_IMETHODIMP 51 HTMLOutputElement::Reset() { 52 mValueModeFlag = eModeDefault; 53 // We can't pass mDefaultValue, because it'll be truncated when 54 // the element's descendants are changed, so pass a copy instead. 55 const nsAutoString currentDefaultValue(mDefaultValue); 56 return nsContentUtils::SetNodeTextContent(this, currentDefaultValue, true); 57 } 58 59 bool HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 60 const nsAString& aValue, 61 nsIPrincipal* aMaybeScriptedPrincipal, 62 nsAttrValue& aResult) { 63 if (aNamespaceID == kNameSpaceID_None) { 64 if (aAttribute == nsGkAtoms::_for) { 65 aResult.ParseAtomArray(aValue); 66 return true; 67 } 68 } 69 70 return nsGenericHTMLFormControlElement::ParseAttribute( 71 aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult); 72 } 73 74 void HTMLOutputElement::DoneAddingChildren(bool aHaveNotified) { 75 mIsDoneAddingChildren = true; 76 // We should update DefaultValue, after parsing is done. 77 DescendantsChanged(); 78 } 79 80 void HTMLOutputElement::GetValue(nsAString& aValue) const { 81 nsContentUtils::GetNodeTextContent(this, true, aValue); 82 } 83 84 void HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv) { 85 mValueModeFlag = eModeValue; 86 aRv = nsContentUtils::SetNodeTextContent(this, aValue, true); 87 } 88 89 void HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, 90 ErrorResult& aRv) { 91 mDefaultValue = aDefaultValue; 92 if (mValueModeFlag == eModeDefault) { 93 // We can't pass mDefaultValue, because it'll be truncated when 94 // the element's descendants are changed. 95 aRv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true); 96 } 97 } 98 99 nsDOMTokenList* HTMLOutputElement::HtmlFor() { 100 if (!mTokenList) { 101 mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for); 102 } 103 return mTokenList; 104 } 105 106 void HTMLOutputElement::DescendantsChanged() { 107 if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) { 108 nsContentUtils::GetNodeTextContent(this, true, mDefaultValue); 109 } 110 } 111 112 // nsIMutationObserver 113 114 void HTMLOutputElement::CharacterDataChanged(nsIContent* aContent, 115 const CharacterDataChangeInfo&) { 116 DescendantsChanged(); 117 } 118 119 void HTMLOutputElement::ContentAppended(nsIContent* aFirstNewContent, 120 const ContentAppendInfo&) { 121 DescendantsChanged(); 122 } 123 124 void HTMLOutputElement::ContentInserted(nsIContent* aChild, 125 const ContentInsertInfo&) { 126 DescendantsChanged(); 127 } 128 129 void HTMLOutputElement::ContentWillBeRemoved(nsIContent* aChild, 130 const ContentRemoveInfo& aInfo) { 131 if (aInfo.mBatchRemovalState && !aInfo.mBatchRemovalState->mIsFirst) { 132 return; 133 } 134 // Make sure to run this once the removal has taken place. 135 nsContentUtils::AddScriptRunner( 136 NewRunnableMethod("HTMLOutputElement::DescendantsChanged", this, 137 &HTMLOutputElement::DescendantsChanged)); 138 } 139 140 JSObject* HTMLOutputElement::WrapNode(JSContext* aCx, 141 JS::Handle<JSObject*> aGivenProto) { 142 return HTMLOutputElement_Binding::Wrap(aCx, this, aGivenProto); 143 } 144 145 } // namespace mozilla::dom