Line data Source code
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/EventStates.h"
11 : #include "mozilla/dom/HTMLFormElement.h"
12 : #include "mozilla/dom/HTMLFormSubmission.h"
13 : #include "mozilla/dom/HTMLOutputElementBinding.h"
14 : #include "nsContentUtils.h"
15 : #include "nsDOMTokenList.h"
16 :
17 0 : NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
18 :
19 : namespace mozilla {
20 : namespace dom {
21 :
22 0 : HTMLOutputElement::HTMLOutputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
23 0 : FromParser aFromParser)
24 : : nsGenericHTMLFormElement(aNodeInfo, NS_FORM_OUTPUT)
25 : , mValueModeFlag(eModeDefault)
26 0 : , mIsDoneAddingChildren(!aFromParser)
27 : {
28 0 : AddMutationObserver(this);
29 :
30 : // We start out valid and ui-valid (since we have no form).
31 0 : AddStatesSilently(NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID);
32 0 : }
33 :
34 0 : HTMLOutputElement::~HTMLOutputElement()
35 : {
36 0 : }
37 :
38 : NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLOutputElement)
39 :
40 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLOutputElement,
41 : nsGenericHTMLFormElement)
42 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
43 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mTokenList)
44 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
45 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLOutputElement,
46 : nsGenericHTMLFormElement)
47 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
48 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
49 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
50 :
51 0 : NS_IMPL_ADDREF_INHERITED(HTMLOutputElement, Element)
52 0 : NS_IMPL_RELEASE_INHERITED(HTMLOutputElement, Element)
53 :
54 0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLOutputElement)
55 0 : NS_INTERFACE_TABLE_INHERITED(HTMLOutputElement,
56 : nsIMutationObserver,
57 : nsIConstraintValidation)
58 0 : NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLFormElement)
59 :
60 0 : NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
61 :
62 : void
63 0 : HTMLOutputElement::SetCustomValidity(const nsAString& aError)
64 : {
65 0 : nsIConstraintValidation::SetCustomValidity(aError);
66 :
67 0 : UpdateState(true);
68 0 : }
69 :
70 : NS_IMETHODIMP
71 0 : HTMLOutputElement::Reset()
72 : {
73 0 : mValueModeFlag = eModeDefault;
74 0 : return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
75 : }
76 :
77 : NS_IMETHODIMP
78 0 : HTMLOutputElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
79 : {
80 : // The output element is not submittable.
81 0 : return NS_OK;
82 : }
83 :
84 : bool
85 0 : HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
86 : const nsAString& aValue, nsAttrValue& aResult)
87 : {
88 0 : if (aNamespaceID == kNameSpaceID_None) {
89 0 : if (aAttribute == nsGkAtoms::_for) {
90 0 : aResult.ParseAtomArray(aValue);
91 0 : return true;
92 : }
93 : }
94 :
95 0 : return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
96 0 : aValue, aResult);
97 : }
98 :
99 : void
100 0 : HTMLOutputElement::DoneAddingChildren(bool aHaveNotified)
101 : {
102 0 : mIsDoneAddingChildren = true;
103 0 : }
104 :
105 : EventStates
106 0 : HTMLOutputElement::IntrinsicState() const
107 : {
108 0 : EventStates states = nsGenericHTMLFormElement::IntrinsicState();
109 :
110 : // We don't have to call IsCandidateForConstraintValidation()
111 : // because <output> can't be barred from constraint validation.
112 0 : if (IsValid()) {
113 0 : states |= NS_EVENT_STATE_VALID;
114 0 : if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
115 0 : states |= NS_EVENT_STATE_MOZ_UI_VALID;
116 : }
117 : } else {
118 0 : states |= NS_EVENT_STATE_INVALID;
119 0 : if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
120 0 : states |= NS_EVENT_STATE_MOZ_UI_INVALID;
121 : }
122 : }
123 :
124 0 : return states;
125 : }
126 :
127 : nsresult
128 0 : HTMLOutputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
129 : nsIContent* aBindingParent,
130 : bool aCompileEventHandlers)
131 : {
132 0 : nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
133 : aBindingParent,
134 0 : aCompileEventHandlers);
135 0 : NS_ENSURE_SUCCESS(rv, rv);
136 :
137 : // Unfortunately, we can actually end up having to change our state
138 : // as a result of being bound to a tree even from the parser: we
139 : // might end up a in a novalidate form, and unlike other form
140 : // controls that on its own is enough to make change ui-valid state.
141 : // So just go ahead and update our state now.
142 0 : UpdateState(false);
143 :
144 0 : return rv;
145 : }
146 :
147 : void
148 0 : HTMLOutputElement::GetValue(nsAString& aValue)
149 : {
150 0 : nsContentUtils::GetNodeTextContent(this, true, aValue);
151 0 : }
152 :
153 : void
154 0 : HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
155 : {
156 0 : mValueModeFlag = eModeValue;
157 0 : aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
158 0 : }
159 :
160 : void
161 0 : HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
162 : {
163 0 : mDefaultValue = aDefaultValue;
164 0 : if (mValueModeFlag == eModeDefault) {
165 0 : aRv = nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
166 : }
167 0 : }
168 :
169 : nsDOMTokenList*
170 0 : HTMLOutputElement::HtmlFor()
171 : {
172 0 : if (!mTokenList) {
173 0 : mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
174 : }
175 0 : return mTokenList;
176 : }
177 :
178 0 : void HTMLOutputElement::DescendantsChanged()
179 : {
180 0 : if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) {
181 0 : nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
182 : }
183 0 : }
184 :
185 : // nsIMutationObserver
186 :
187 0 : void HTMLOutputElement::CharacterDataChanged(nsIDocument* aDocument,
188 : nsIContent* aContent,
189 : CharacterDataChangeInfo* aInfo)
190 : {
191 0 : DescendantsChanged();
192 0 : }
193 :
194 0 : void HTMLOutputElement::ContentAppended(nsIDocument* aDocument,
195 : nsIContent* aContainer,
196 : nsIContent* aFirstNewContent,
197 : int32_t aNewIndexInContainer)
198 : {
199 0 : DescendantsChanged();
200 0 : }
201 :
202 0 : void HTMLOutputElement::ContentInserted(nsIDocument* aDocument,
203 : nsIContent* aContainer,
204 : nsIContent* aChild,
205 : int32_t aIndexInContainer)
206 : {
207 0 : DescendantsChanged();
208 0 : }
209 :
210 0 : void HTMLOutputElement::ContentRemoved(nsIDocument* aDocument,
211 : nsIContent* aContainer,
212 : nsIContent* aChild,
213 : int32_t aIndexInContainer,
214 : nsIContent* aPreviousSibling)
215 : {
216 0 : DescendantsChanged();
217 0 : }
218 :
219 : JSObject*
220 0 : HTMLOutputElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
221 : {
222 0 : return HTMLOutputElementBinding::Wrap(aCx, this, aGivenProto);
223 : }
224 :
225 : } // namespace dom
226 : } // namespace mozilla
|