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/. */
7 #include "mozilla/EventDispatcher.h"
8 #include "mozilla/EventStates.h"
9 #include "mozilla/dom/HTMLOptGroupElement.h"
10 #include "mozilla/dom/HTMLOptGroupElementBinding.h"
11 #include "mozilla/dom/HTMLSelectElement.h" // SafeOptionListMutation
12 #include "nsGkAtoms.h"
13 #include "nsStyleConsts.h"
15 #include "nsIFormControlFrame.h"
17 NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup
)
23 * The implementation of <optgroup>
26 HTMLOptGroupElement::HTMLOptGroupElement(
27 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
)
28 : nsGenericHTMLElement(std::move(aNodeInfo
)) {
29 // We start off enabled
30 AddStatesSilently(NS_EVENT_STATE_ENABLED
);
33 HTMLOptGroupElement::~HTMLOptGroupElement() {}
35 NS_IMPL_ELEMENT_CLONE(HTMLOptGroupElement
)
37 void HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor
& aVisitor
) {
38 aVisitor
.mCanHandle
= false;
40 if (nsIFrame
* frame
= GetPrimaryFrame()) {
41 // FIXME(emilio): This poking at the style of the frame is broken unless we
42 // flush before every event handling, which we don't really want to.
43 if (frame
->StyleUI()->mUserInput
== StyleUserInput::None
) {
48 nsGenericHTMLElement::GetEventTargetParent(aVisitor
);
51 Element
* HTMLOptGroupElement::GetSelect() {
52 Element
* parent
= nsINode::GetParentElement();
53 if (!parent
|| !parent
->IsHTMLElement(nsGkAtoms::select
)) {
59 nsresult
HTMLOptGroupElement::InsertChildBefore(nsIContent
* aKid
,
60 nsIContent
* aBeforeThis
,
62 int32_t index
= aBeforeThis
? ComputeIndexOf(aBeforeThis
) : GetChildCount();
63 SafeOptionListMutation
safeMutation(GetSelect(), this, aKid
, index
, aNotify
);
65 nsGenericHTMLElement::InsertChildBefore(aKid
, aBeforeThis
, aNotify
);
67 safeMutation
.MutationFailed();
72 void HTMLOptGroupElement::RemoveChildNode(nsIContent
* aKid
, bool aNotify
) {
73 SafeOptionListMutation
safeMutation(GetSelect(), this, nullptr,
74 ComputeIndexOf(aKid
), aNotify
);
75 nsGenericHTMLElement::RemoveChildNode(aKid
, aNotify
);
78 nsresult
HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID
, nsAtom
* aName
,
79 const nsAttrValue
* aValue
,
80 const nsAttrValue
* aOldValue
,
81 nsIPrincipal
* aSubjectPrincipal
,
83 if (aNameSpaceID
== kNameSpaceID_None
&& aName
== nsGkAtoms::disabled
) {
84 EventStates disabledStates
;
86 disabledStates
|= NS_EVENT_STATE_DISABLED
;
88 disabledStates
|= NS_EVENT_STATE_ENABLED
;
91 EventStates oldDisabledStates
= State() & DISABLED_STATES
;
92 EventStates changedStates
= disabledStates
^ oldDisabledStates
;
94 if (!changedStates
.IsEmpty()) {
95 ToggleStates(changedStates
, aNotify
);
97 // All our children <option> have their :disabled state depending on our
98 // disabled attribute. We should make sure their state is updated.
99 for (nsIContent
* child
= nsINode::GetFirstChild(); child
;
100 child
= child
->GetNextSibling()) {
101 if (auto optElement
= HTMLOptionElement::FromNode(child
)) {
102 optElement
->OptGroupDisabledChanged(true);
108 return nsGenericHTMLElement::AfterSetAttr(
109 aNameSpaceID
, aName
, aValue
, aOldValue
, aSubjectPrincipal
, aNotify
);
112 JSObject
* HTMLOptGroupElement::WrapNode(JSContext
* aCx
,
113 JS::Handle
<JSObject
*> aGivenProto
) {
114 return HTMLOptGroupElement_Binding::Wrap(aCx
, this, aGivenProto
);
118 } // namespace mozilla