forked from mirrors/gecko-dev
		
	 1ed2ba9764
			
		
	
	
		1ed2ba9764
		
	
	
	
	
		
			
			Differential Revision: https://phabricator.services.mozilla.com/D63171 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			176 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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/. */
 | |
| 
 | |
| #include "mozilla/dom/HTMLOutputElement.h"
 | |
| 
 | |
| #include "mozAutoDocUpdate.h"
 | |
| #include "mozilla/EventStates.h"
 | |
| #include "mozilla/dom/HTMLFormElement.h"
 | |
| #include "mozilla/dom/HTMLFormSubmission.h"
 | |
| #include "mozilla/dom/HTMLOutputElementBinding.h"
 | |
| #include "nsContentUtils.h"
 | |
| #include "nsDOMTokenList.h"
 | |
| 
 | |
| NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace dom {
 | |
| 
 | |
| HTMLOutputElement::HTMLOutputElement(
 | |
|     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
 | |
|     FromParser aFromParser)
 | |
|     : nsGenericHTMLFormElement(std::move(aNodeInfo), NS_FORM_OUTPUT),
 | |
|       mValueModeFlag(eModeDefault),
 | |
|       mIsDoneAddingChildren(!aFromParser) {
 | |
|   AddMutationObserver(this);
 | |
| 
 | |
|   // We start out valid and ui-valid (since we have no form).
 | |
|   AddStatesSilently(NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID);
 | |
| }
 | |
| 
 | |
| HTMLOutputElement::~HTMLOutputElement() = default;
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLOutputElement, nsGenericHTMLFormElement,
 | |
|                                    mValidity, mTokenList)
 | |
| 
 | |
| NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLOutputElement,
 | |
|                                              nsGenericHTMLFormElement,
 | |
|                                              nsIMutationObserver,
 | |
|                                              nsIConstraintValidation)
 | |
| 
 | |
| NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
 | |
| 
 | |
| void HTMLOutputElement::SetCustomValidity(const nsAString& aError) {
 | |
|   nsIConstraintValidation::SetCustomValidity(aError);
 | |
| 
 | |
|   UpdateState(true);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| HTMLOutputElement::Reset() {
 | |
|   mValueModeFlag = eModeDefault;
 | |
|   return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| HTMLOutputElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission) {
 | |
|   // The output element is not submittable.
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| bool HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
 | |
|                                        const nsAString& aValue,
 | |
|                                        nsIPrincipal* aMaybeScriptedPrincipal,
 | |
|                                        nsAttrValue& aResult) {
 | |
|   if (aNamespaceID == kNameSpaceID_None) {
 | |
|     if (aAttribute == nsGkAtoms::_for) {
 | |
|       aResult.ParseAtomArray(aValue);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return nsGenericHTMLFormElement::ParseAttribute(
 | |
|       aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult);
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::DoneAddingChildren(bool aHaveNotified) {
 | |
|   mIsDoneAddingChildren = true;
 | |
| }
 | |
| 
 | |
| EventStates HTMLOutputElement::IntrinsicState() const {
 | |
|   EventStates states = nsGenericHTMLFormElement::IntrinsicState();
 | |
| 
 | |
|   // We don't have to call IsCandidateForConstraintValidation()
 | |
|   // because <output> can't be barred from constraint validation.
 | |
|   if (IsValid()) {
 | |
|     states |= NS_EVENT_STATE_VALID;
 | |
|     if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
 | |
|       states |= NS_EVENT_STATE_MOZ_UI_VALID;
 | |
|     }
 | |
|   } else {
 | |
|     states |= NS_EVENT_STATE_INVALID;
 | |
|     if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
 | |
|       states |= NS_EVENT_STATE_MOZ_UI_INVALID;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return states;
 | |
| }
 | |
| 
 | |
| nsresult HTMLOutputElement::BindToTree(BindContext& aContext,
 | |
|                                        nsINode& aParent) {
 | |
|   nsresult rv = nsGenericHTMLFormElement::BindToTree(aContext, aParent);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   // Unfortunately, we can actually end up having to change our state
 | |
|   // as a result of being bound to a tree even from the parser: we
 | |
|   // might end up a in a novalidate form, and unlike other form
 | |
|   // controls that on its own is enough to make change ui-valid state.
 | |
|   // So just go ahead and update our state now.
 | |
|   UpdateState(false);
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::GetValue(nsAString& aValue) {
 | |
|   nsContentUtils::GetNodeTextContent(this, true, aValue);
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv) {
 | |
|   mValueModeFlag = eModeValue;
 | |
|   aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue,
 | |
|                                         ErrorResult& aRv) {
 | |
|   mDefaultValue = aDefaultValue;
 | |
|   if (mValueModeFlag == eModeDefault) {
 | |
|     // We can't pass mDefaultValue, because it'll be truncated when
 | |
|     // the element's descendants are changed.
 | |
|     aRv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true);
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsDOMTokenList* HTMLOutputElement::HtmlFor() {
 | |
|   if (!mTokenList) {
 | |
|     mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
 | |
|   }
 | |
|   return mTokenList;
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::DescendantsChanged() {
 | |
|   if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) {
 | |
|     nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // nsIMutationObserver
 | |
| 
 | |
| void HTMLOutputElement::CharacterDataChanged(nsIContent* aContent,
 | |
|                                              const CharacterDataChangeInfo&) {
 | |
|   DescendantsChanged();
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::ContentAppended(nsIContent* aFirstNewContent) {
 | |
|   DescendantsChanged();
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::ContentInserted(nsIContent* aChild) {
 | |
|   DescendantsChanged();
 | |
| }
 | |
| 
 | |
| void HTMLOutputElement::ContentRemoved(nsIContent* aChild,
 | |
|                                        nsIContent* aPreviousSibling) {
 | |
|   DescendantsChanged();
 | |
| }
 | |
| 
 | |
| JSObject* HTMLOutputElement::WrapNode(JSContext* aCx,
 | |
|                                       JS::Handle<JSObject*> aGivenProto) {
 | |
|   return HTMLOutputElement_Binding::Wrap(aCx, this, aGivenProto);
 | |
| }
 | |
| 
 | |
| }  // namespace dom
 | |
| }  // namespace mozilla
 |