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/HTMLLegendElement.h"
8 #include "mozilla/dom/HTMLLegendElementBinding.h"
9 #include "nsFocusManager.h"
10 #include "nsIFrame.h"
11 
12 NS_IMPL_NS_NEW_HTML_ELEMENT(Legend)
13 
14 namespace mozilla {
15 namespace dom {
16 
~HTMLLegendElement()17 HTMLLegendElement::~HTMLLegendElement() {}
18 
NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)19 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
20 
21 nsIContent* HTMLLegendElement::GetFieldSet() const {
22   nsIContent* parent = GetParent();
23 
24   if (parent && parent->IsHTMLElement(nsGkAtoms::fieldset)) {
25     return parent;
26   }
27 
28   return nullptr;
29 }
30 
ParseAttribute(int32_t aNamespaceID,nsAtom * aAttribute,const nsAString & aValue,nsIPrincipal * aMaybeScriptedPrincipal,nsAttrValue & aResult)31 bool HTMLLegendElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
32                                        const nsAString& aValue,
33                                        nsIPrincipal* aMaybeScriptedPrincipal,
34                                        nsAttrValue& aResult) {
35   // this contains center, because IE4 does
36   static const nsAttrValue::EnumTable kAlignTable[] = {
37       {"left", NS_STYLE_TEXT_ALIGN_LEFT},
38       {"right", NS_STYLE_TEXT_ALIGN_RIGHT},
39       {"center", NS_STYLE_TEXT_ALIGN_CENTER},
40       {"bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM},
41       {"top", NS_STYLE_VERTICAL_ALIGN_TOP},
42       {nullptr, 0}};
43 
44   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
45     return aResult.ParseEnumValue(aValue, kAlignTable, false);
46   }
47 
48   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
49                                               aMaybeScriptedPrincipal, aResult);
50 }
51 
GetAttributeChangeHint(const nsAtom * aAttribute,int32_t aModType) const52 nsChangeHint HTMLLegendElement::GetAttributeChangeHint(const nsAtom* aAttribute,
53                                                        int32_t aModType) const {
54   nsChangeHint retval =
55       nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
56   if (aAttribute == nsGkAtoms::align) {
57     retval |= NS_STYLE_HINT_REFLOW;
58   }
59   return retval;
60 }
61 
BindToTree(nsIDocument * aDocument,nsIContent * aParent,nsIContent * aBindingParent,bool aCompileEventHandlers)62 nsresult HTMLLegendElement::BindToTree(nsIDocument* aDocument,
63                                        nsIContent* aParent,
64                                        nsIContent* aBindingParent,
65                                        bool aCompileEventHandlers) {
66   return nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent,
67                                           aCompileEventHandlers);
68 }
69 
UnbindFromTree(bool aDeep,bool aNullParent)70 void HTMLLegendElement::UnbindFromTree(bool aDeep, bool aNullParent) {
71   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
72 }
73 
Focus(ErrorResult & aError)74 void HTMLLegendElement::Focus(ErrorResult& aError) {
75   nsIFrame* frame = GetPrimaryFrame();
76   if (!frame) {
77     return;
78   }
79 
80   int32_t tabIndex;
81   if (frame->IsFocusable(&tabIndex, false)) {
82     nsGenericHTMLElement::Focus(aError);
83     return;
84   }
85 
86   // If the legend isn't focusable, focus whatever is focusable following
87   // the legend instead, bug 81481.
88   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
89   if (!fm) {
90     return;
91   }
92 
93   nsCOMPtr<nsIDOMElement> result;
94   aError = fm->MoveFocus(nullptr, this, nsIFocusManager::MOVEFOCUS_FORWARD,
95                          nsIFocusManager::FLAG_NOPARENTFRAME,
96                          getter_AddRefs(result));
97 }
98 
PerformAccesskey(bool aKeyCausesActivation,bool aIsTrustedEvent)99 bool HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
100                                          bool aIsTrustedEvent) {
101   // just use the same behaviour as the focus method
102   ErrorResult rv;
103   Focus(rv);
104   return NS_SUCCEEDED(rv.StealNSResult());
105 }
106 
GetForm()107 already_AddRefed<HTMLFormElement> HTMLLegendElement::GetForm() {
108   Element* form = GetFormElement();
109   MOZ_ASSERT_IF(form, form->IsHTMLElement(nsGkAtoms::form));
110   RefPtr<HTMLFormElement> ret = static_cast<HTMLFormElement*>(form);
111   return ret.forget();
112 }
113 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)114 JSObject* HTMLLegendElement::WrapNode(JSContext* aCx,
115                                       JS::Handle<JSObject*> aGivenProto) {
116   return HTMLLegendElementBinding::Wrap(aCx, this, aGivenProto);
117 }
118 
119 }  // namespace dom
120 }  // namespace mozilla
121