1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/EventDispatcher.h"
7 #include "mozilla/EventStates.h"
8 #include "mozilla/dom/HTMLOptGroupElement.h"
9 #include "mozilla/dom/HTMLOptGroupElementBinding.h"
10 #include "mozilla/dom/HTMLSelectElement.h" // SafeOptionListMutation
11 #include "nsGkAtoms.h"
12 #include "nsStyleConsts.h"
14 #include "nsIFormControlFrame.h"
16 NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup
)
22 * The implementation of <optgroup>
27 HTMLOptGroupElement::HTMLOptGroupElement(already_AddRefed
<mozilla::dom::NodeInfo
>& aNodeInfo
)
28 : nsGenericHTMLElement(aNodeInfo
)
30 // We start off enabled
31 AddStatesSilently(NS_EVENT_STATE_ENABLED
);
34 HTMLOptGroupElement::~HTMLOptGroupElement()
39 NS_IMPL_ISUPPORTS_INHERITED(HTMLOptGroupElement
, nsGenericHTMLElement
,
40 nsIDOMHTMLOptGroupElement
)
42 NS_IMPL_ELEMENT_CLONE(HTMLOptGroupElement
)
45 NS_IMPL_BOOL_ATTR(HTMLOptGroupElement
, Disabled
, disabled
)
46 NS_IMPL_STRING_ATTR(HTMLOptGroupElement
, Label
, label
)
50 HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor
& aVisitor
)
52 aVisitor
.mCanHandle
= false;
53 // Do not process any DOM events if the element is disabled
54 // XXXsmaug This is not the right thing to do. But what is?
55 if (HasAttr(kNameSpaceID_None
, nsGkAtoms::disabled
)) {
59 nsIFrame
* frame
= GetPrimaryFrame();
61 const nsStyleUserInterface
* uiStyle
= frame
->StyleUserInterface();
62 if (uiStyle
->mUserInput
== NS_STYLE_USER_INPUT_NONE
||
63 uiStyle
->mUserInput
== NS_STYLE_USER_INPUT_DISABLED
) {
68 return nsGenericHTMLElement::PreHandleEvent(aVisitor
);
72 HTMLOptGroupElement::GetSelect()
74 nsIContent
* parent
= this;
75 while ((parent
= parent
->GetParent()) && parent
->IsHTML()) {
76 if (parent
->Tag() == nsGkAtoms::select
) {
79 if (parent
->Tag() != nsGkAtoms::optgroup
) {
88 HTMLOptGroupElement::InsertChildAt(nsIContent
* aKid
,
92 SafeOptionListMutation
safeMutation(GetSelect(), this, aKid
, aIndex
, aNotify
);
93 nsresult rv
= nsGenericHTMLElement::InsertChildAt(aKid
, aIndex
, aNotify
);
95 safeMutation
.MutationFailed();
101 HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex
, bool aNotify
)
103 SafeOptionListMutation
safeMutation(GetSelect(), this, nullptr, aIndex
,
105 nsGenericHTMLElement::RemoveChildAt(aIndex
, aNotify
);
109 HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID
, nsIAtom
* aName
,
110 const nsAttrValue
* aValue
, bool aNotify
)
112 if (aNameSpaceID
== kNameSpaceID_None
&& aName
== nsGkAtoms::disabled
) {
113 // All our children <option> have their :disabled state depending on our
114 // disabled attribute. We should make sure their state is updated.
115 for (nsIContent
* child
= nsINode::GetFirstChild(); child
;
116 child
= child
->GetNextSibling()) {
117 if (child
->IsHTML(nsGkAtoms::option
)) {
118 // No need to call |IsElement()| because it's an HTML element.
119 child
->AsElement()->UpdateState(true);
124 return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID
, aName
, aValue
,
129 HTMLOptGroupElement::IntrinsicState() const
131 EventStates state
= nsGenericHTMLElement::IntrinsicState();
133 if (HasAttr(kNameSpaceID_None
, nsGkAtoms::disabled
)) {
134 state
|= NS_EVENT_STATE_DISABLED
;
135 state
&= ~NS_EVENT_STATE_ENABLED
;
137 state
&= ~NS_EVENT_STATE_DISABLED
;
138 state
|= NS_EVENT_STATE_ENABLED
;
145 HTMLOptGroupElement::WrapNode(JSContext
* aCx
)
147 return HTMLOptGroupElementBinding::Wrap(aCx
, this);
151 } // namespace mozilla