HTMLLegendElement.cpp (4666B)
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 9 #include "mozilla/dom/ElementBinding.h" 10 #include "mozilla/dom/HTMLLegendElementBinding.h" 11 #include "nsFocusManager.h" 12 #include "nsIFrame.h" 13 14 NS_IMPL_NS_NEW_HTML_ELEMENT(Legend) 15 16 namespace mozilla::dom { 17 18 HTMLLegendElement::~HTMLLegendElement() = default; 19 20 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement) 21 22 nsIContent* HTMLLegendElement::GetFieldSet() const { 23 nsIContent* parent = GetParent(); 24 25 if (parent && parent->IsHTMLElement(nsGkAtoms::fieldset)) { 26 return parent; 27 } 28 29 return nullptr; 30 } 31 32 bool HTMLLegendElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 33 const nsAString& aValue, 34 nsIPrincipal* aMaybeScriptedPrincipal, 35 nsAttrValue& aResult) { 36 // this contains center, because IE4 does 37 static constexpr nsAttrValue::EnumTableEntry kAlignTable[] = { 38 {"left", LegendAlignValue::Left}, 39 {"right", LegendAlignValue::Right}, 40 {"center", LegendAlignValue::Center}, 41 }; 42 43 if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) { 44 return aResult.ParseEnumValue(aValue, kAlignTable, false); 45 } 46 47 return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, 48 aMaybeScriptedPrincipal, aResult); 49 } 50 51 nsChangeHint HTMLLegendElement::GetAttributeChangeHint( 52 const nsAtom* aAttribute, AttrModType aModType) const { 53 nsChangeHint retval = 54 nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType); 55 if (aAttribute == nsGkAtoms::align) { 56 retval |= NS_STYLE_HINT_REFLOW; 57 } 58 return retval; 59 } 60 61 nsresult HTMLLegendElement::BindToTree(BindContext& aContext, 62 nsINode& aParent) { 63 return nsGenericHTMLElement::BindToTree(aContext, aParent); 64 } 65 66 void HTMLLegendElement::UnbindFromTree(UnbindContext& aContext) { 67 nsGenericHTMLElement::UnbindFromTree(aContext); 68 } 69 70 void HTMLLegendElement::Focus(const FocusOptions& aOptions, 71 const CallerType aCallerType, 72 ErrorResult& aError) { 73 nsIFrame* frame = GetPrimaryFrame(); 74 if (!frame) { 75 return; 76 } 77 78 if (frame->IsFocusable()) { 79 nsGenericHTMLElement::Focus(aOptions, aCallerType, aError); 80 return; 81 } 82 83 // If the legend isn't focusable, focus whatever is focusable following 84 // the legend instead, bug 81481. 85 nsFocusManager* fm = nsFocusManager::GetFocusManager(); 86 if (!fm) { 87 return; 88 } 89 90 RefPtr<Element> result; 91 aError = fm->MoveFocus(nullptr, this, nsIFocusManager::MOVEFOCUS_FORWARD, 92 nsIFocusManager::FLAG_NOPARENTFRAME | 93 nsFocusManager::ProgrammaticFocusFlags(aOptions), 94 getter_AddRefs(result)); 95 } 96 97 Result<bool, nsresult> HTMLLegendElement::PerformAccesskey( 98 bool aKeyCausesActivation, bool aIsTrustedEvent) { 99 FocusOptions options; 100 ErrorResult rv; 101 102 Focus(options, CallerType::System, rv); 103 if (rv.Failed()) { 104 return Err(rv.StealNSResult()); 105 } 106 107 // XXXedgar, do we need to check whether the focus is really changed? 108 return true; 109 } 110 111 HTMLLegendElement::LegendAlignValue HTMLLegendElement::LogicalAlign( 112 mozilla::WritingMode aCBWM) const { 113 const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::align); 114 if (!attr || attr->Type() != nsAttrValue::eEnum) { 115 return LegendAlignValue::InlineStart; 116 } 117 118 auto value = static_cast<LegendAlignValue>(attr->GetEnumValue()); 119 switch (value) { 120 case LegendAlignValue::Left: 121 return aCBWM.IsBidiLTR() ? LegendAlignValue::InlineStart 122 : LegendAlignValue::InlineEnd; 123 case LegendAlignValue::Right: 124 return aCBWM.IsBidiLTR() ? LegendAlignValue::InlineEnd 125 : LegendAlignValue::InlineStart; 126 default: 127 return value; 128 } 129 } 130 131 HTMLFormElement* HTMLLegendElement::GetForm() const { 132 const auto* fieldsetControl = nsIFormControl::FromNodeOrNull(GetFieldSet()); 133 return fieldsetControl ? fieldsetControl->GetForm() : nullptr; 134 } 135 136 JSObject* HTMLLegendElement::WrapNode(JSContext* aCx, 137 JS::Handle<JSObject*> aGivenProto) { 138 return HTMLLegendElement_Binding::Wrap(aCx, this, aGivenProto); 139 } 140 141 } // namespace mozilla::dom