HTMLOptGroupElement.cpp (4050B)
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/HTMLOptGroupElement.h" 8 9 #include "mozilla/EventDispatcher.h" 10 #include "mozilla/dom/HTMLOptGroupElementBinding.h" 11 #include "mozilla/dom/HTMLSelectElement.h" // SafeOptionListMutation 12 #include "nsGkAtoms.h" 13 #include "nsIFrame.h" 14 #include "nsStyleConsts.h" 15 16 NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup) 17 18 namespace mozilla::dom { 19 20 /** 21 * The implementation of <optgroup> 22 */ 23 24 HTMLOptGroupElement::HTMLOptGroupElement( 25 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) 26 : nsGenericHTMLElement(std::move(aNodeInfo)) { 27 // We start off enabled 28 AddStatesSilently(ElementState::ENABLED); 29 } 30 31 HTMLOptGroupElement::~HTMLOptGroupElement() = default; 32 33 NS_IMPL_ELEMENT_CLONE(HTMLOptGroupElement) 34 35 void HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { 36 aVisitor.mCanHandle = false; 37 nsGenericHTMLElement::GetEventTargetParent(aVisitor); 38 } 39 40 Element* HTMLOptGroupElement::GetSelect() { 41 Element* parent = nsINode::GetParentElement(); 42 if (!parent || !parent->IsHTMLElement(nsGkAtoms::select)) { 43 return nullptr; 44 } 45 return parent; 46 } 47 48 void HTMLOptGroupElement::InsertChildBefore( 49 nsIContent* aKid, nsIContent* aBeforeThis, bool aNotify, ErrorResult& aRv, 50 nsINode* aOldParent, MutationEffectOnScript aMutationEffectOnScript) { 51 const uint32_t index = 52 aBeforeThis ? *ComputeIndexOf(aBeforeThis) : GetChildCount(); 53 SafeOptionListMutation safeMutation(GetSelect(), this, aKid, index, aNotify); 54 nsGenericHTMLElement::InsertChildBefore(aKid, aBeforeThis, aNotify, aRv, 55 aOldParent, aMutationEffectOnScript); 56 if (aRv.Failed()) { 57 safeMutation.MutationFailed(); 58 } 59 } 60 61 void HTMLOptGroupElement::RemoveChildNode( 62 nsIContent* aKid, bool aNotify, const BatchRemovalState* aState, 63 nsINode* aNewParent, MutationEffectOnScript aMutationEffectOnScript) { 64 SafeOptionListMutation safeMutation(GetSelect(), this, nullptr, 65 *ComputeIndexOf(aKid), aNotify); 66 nsGenericHTMLElement::RemoveChildNode(aKid, aNotify, aState, aNewParent, 67 aMutationEffectOnScript); 68 } 69 70 void HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, 71 const nsAttrValue* aValue, 72 const nsAttrValue* aOldValue, 73 nsIPrincipal* aSubjectPrincipal, 74 bool aNotify) { 75 if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) { 76 ElementState disabledStates; 77 if (aValue) { 78 disabledStates |= ElementState::DISABLED; 79 } else { 80 disabledStates |= ElementState::ENABLED; 81 } 82 83 ElementState oldDisabledStates = State() & ElementState::DISABLED_STATES; 84 ElementState changedStates = disabledStates ^ oldDisabledStates; 85 86 if (!changedStates.IsEmpty()) { 87 ToggleStates(changedStates, aNotify); 88 89 // All our children <option> have their :disabled state depending on our 90 // disabled attribute. We should make sure their state is updated. 91 for (nsIContent* child = nsINode::GetFirstChild(); child; 92 child = child->GetNextSibling()) { 93 if (auto optElement = HTMLOptionElement::FromNode(child)) { 94 optElement->OptGroupDisabledChanged(true); 95 } 96 } 97 } 98 } 99 100 return nsGenericHTMLElement::AfterSetAttr( 101 aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); 102 } 103 104 JSObject* HTMLOptGroupElement::WrapNode(JSContext* aCx, 105 JS::Handle<JSObject*> aGivenProto) { 106 return HTMLOptGroupElement_Binding::Wrap(aCx, this, aGivenProto); 107 } 108 109 } // namespace mozilla::dom