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/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"
14 : #include "nsIFrame.h"
15 : #include "nsIFormControlFrame.h"
16 :
17 0 : NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup)
18 :
19 : namespace mozilla {
20 : namespace dom {
21 :
22 : /**
23 : * The implementation of <optgroup>
24 : */
25 :
26 :
27 :
28 0 : HTMLOptGroupElement::HTMLOptGroupElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
29 0 : : nsGenericHTMLElement(aNodeInfo)
30 : {
31 : // We start off enabled
32 0 : AddStatesSilently(NS_EVENT_STATE_ENABLED);
33 0 : }
34 :
35 0 : HTMLOptGroupElement::~HTMLOptGroupElement()
36 : {
37 0 : }
38 :
39 :
40 0 : NS_IMPL_ISUPPORTS_INHERITED(HTMLOptGroupElement, nsGenericHTMLElement,
41 : nsIDOMHTMLOptGroupElement)
42 :
43 0 : NS_IMPL_ELEMENT_CLONE(HTMLOptGroupElement)
44 :
45 :
46 0 : NS_IMPL_BOOL_ATTR(HTMLOptGroupElement, Disabled, disabled)
47 0 : NS_IMPL_STRING_ATTR(HTMLOptGroupElement, Label, label)
48 :
49 :
50 : nsresult
51 0 : HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
52 : {
53 0 : aVisitor.mCanHandle = false;
54 : // Do not process any DOM events if the element is disabled
55 : // XXXsmaug This is not the right thing to do. But what is?
56 0 : if (HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
57 0 : return NS_OK;
58 : }
59 :
60 0 : nsIFrame* frame = GetPrimaryFrame();
61 0 : if (frame) {
62 0 : const nsStyleUserInterface* uiStyle = frame->StyleUserInterface();
63 0 : if (uiStyle->mUserInput == StyleUserInput::None ||
64 0 : uiStyle->mUserInput == StyleUserInput::Disabled) {
65 0 : return NS_OK;
66 : }
67 : }
68 :
69 0 : return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
70 : }
71 :
72 : Element*
73 0 : HTMLOptGroupElement::GetSelect()
74 : {
75 0 : Element* parent = nsINode::GetParentElement();
76 0 : if (!parent || !parent->IsHTMLElement(nsGkAtoms::select)) {
77 0 : return nullptr;
78 : }
79 0 : return parent;
80 : }
81 :
82 : nsresult
83 0 : HTMLOptGroupElement::InsertChildAt(nsIContent* aKid,
84 : uint32_t aIndex,
85 : bool aNotify)
86 : {
87 0 : SafeOptionListMutation safeMutation(GetSelect(), this, aKid, aIndex, aNotify);
88 0 : nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
89 0 : if (NS_FAILED(rv)) {
90 0 : safeMutation.MutationFailed();
91 : }
92 0 : return rv;
93 : }
94 :
95 : void
96 0 : HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
97 : {
98 0 : SafeOptionListMutation safeMutation(GetSelect(), this, nullptr, aIndex,
99 0 : aNotify);
100 0 : nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
101 0 : }
102 :
103 : nsresult
104 0 : HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
105 : const nsAttrValue* aValue,
106 : const nsAttrValue* aOldValue, bool aNotify)
107 : {
108 0 : if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
109 : // All our children <option> have their :disabled state depending on our
110 : // disabled attribute. We should make sure their state is updated.
111 0 : for (nsIContent* child = nsINode::GetFirstChild(); child;
112 0 : child = child->GetNextSibling()) {
113 0 : if (child->IsHTMLElement(nsGkAtoms::option)) {
114 : // No need to call |IsElement()| because it's an HTML element.
115 0 : child->AsElement()->UpdateState(true);
116 : }
117 : }
118 : }
119 :
120 0 : return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
121 0 : aOldValue, aNotify);
122 : }
123 :
124 : EventStates
125 0 : HTMLOptGroupElement::IntrinsicState() const
126 : {
127 0 : EventStates state = nsGenericHTMLElement::IntrinsicState();
128 :
129 0 : if (HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
130 0 : state |= NS_EVENT_STATE_DISABLED;
131 0 : state &= ~NS_EVENT_STATE_ENABLED;
132 : } else {
133 0 : state &= ~NS_EVENT_STATE_DISABLED;
134 0 : state |= NS_EVENT_STATE_ENABLED;
135 : }
136 :
137 0 : return state;
138 : }
139 :
140 : JSObject*
141 0 : HTMLOptGroupElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
142 : {
143 0 : return HTMLOptGroupElementBinding::Wrap(aCx, this, aGivenProto);
144 : }
145 :
146 : } // namespace dom
147 : } // namespace mozilla
|