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/dom/HTMLMarqueeElement.h"
8 #include "nsGenericHTMLElement.h"
9 #include "nsStyleConsts.h"
10 #include "mozilla/AsyncEventDispatcher.h"
11 #include "mozilla/dom/HTMLMarqueeElementBinding.h"
12 #include "mozilla/dom/CustomEvent.h"
13 // This is to pick up the definition of FunctionStringCallback:
14 #include "mozilla/dom/DataTransferItemBinding.h"
15 #include "mozilla/dom/ShadowRoot.h"
17 NS_IMPL_NS_NEW_HTML_ELEMENT(Marquee
)
19 namespace mozilla::dom
{
21 HTMLMarqueeElement::~HTMLMarqueeElement() = default;
23 NS_IMPL_ELEMENT_CLONE(HTMLMarqueeElement
)
25 static const nsAttrValue::EnumTable kBehaviorTable
[] = {
26 {"scroll", 1}, {"slide", 2}, {"alternate", 3}, {nullptr, 0}};
28 // Default behavior value is "scroll".
29 static const nsAttrValue::EnumTable
* kDefaultBehavior
= &kBehaviorTable
[0];
31 static const nsAttrValue::EnumTable kDirectionTable
[] = {
32 {"left", 1}, {"right", 2}, {"up", 3}, {"down", 4}, {nullptr, 0}};
34 // Default direction value is "left".
35 static const nsAttrValue::EnumTable
* kDefaultDirection
= &kDirectionTable
[0];
37 bool HTMLMarqueeElement::IsEventAttributeNameInternal(nsAtom
* aName
) {
38 return nsContentUtils::IsEventAttributeName(
39 aName
, EventNameType_HTML
| EventNameType_HTMLMarqueeOnly
);
42 JSObject
* HTMLMarqueeElement::WrapNode(JSContext
* aCx
,
43 JS::Handle
<JSObject
*> aGivenProto
) {
44 return dom::HTMLMarqueeElement_Binding::Wrap(aCx
, this, aGivenProto
);
47 nsresult
HTMLMarqueeElement::BindToTree(BindContext
& aContext
,
49 nsresult rv
= nsGenericHTMLElement::BindToTree(aContext
, aParent
);
50 NS_ENSURE_SUCCESS(rv
, rv
);
52 if (IsInComposedDoc()) {
53 AttachAndSetUAShadowRoot();
59 void HTMLMarqueeElement::UnbindFromTree(UnbindContext
& aContext
) {
60 if (IsInComposedDoc()) {
61 // We don't want to unattach the shadow root because it used to
63 NotifyUAWidgetTeardown(UnattachShadowRoot::No
);
66 nsGenericHTMLElement::UnbindFromTree(aContext
);
69 void HTMLMarqueeElement::GetBehavior(nsAString
& aValue
) {
70 GetEnumAttr(nsGkAtoms::behavior
, kDefaultBehavior
->tag
, aValue
);
73 void HTMLMarqueeElement::GetDirection(nsAString
& aValue
) {
74 GetEnumAttr(nsGkAtoms::direction
, kDefaultDirection
->tag
, aValue
);
77 bool HTMLMarqueeElement::ParseAttribute(int32_t aNamespaceID
,
79 const nsAString
& aValue
,
80 nsIPrincipal
* aMaybeScriptedPrincipal
,
81 nsAttrValue
& aResult
) {
82 if (aNamespaceID
== kNameSpaceID_None
) {
83 if ((aAttribute
== nsGkAtoms::width
) || (aAttribute
== nsGkAtoms::height
)) {
84 return aResult
.ParseHTMLDimension(aValue
);
86 if (aAttribute
== nsGkAtoms::bgcolor
) {
87 return aResult
.ParseColor(aValue
);
89 if (aAttribute
== nsGkAtoms::behavior
) {
90 return aResult
.ParseEnumValue(aValue
, kBehaviorTable
, false,
93 if (aAttribute
== nsGkAtoms::direction
) {
94 return aResult
.ParseEnumValue(aValue
, kDirectionTable
, false,
97 if (aAttribute
== nsGkAtoms::hspace
|| aAttribute
== nsGkAtoms::vspace
) {
98 return aResult
.ParseHTMLDimension(aValue
);
101 if (aAttribute
== nsGkAtoms::loop
) {
102 return aResult
.ParseIntValue(aValue
);
105 if (aAttribute
== nsGkAtoms::scrollamount
||
106 aAttribute
== nsGkAtoms::scrolldelay
) {
107 return aResult
.ParseNonNegativeIntValue(aValue
);
111 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
112 aMaybeScriptedPrincipal
, aResult
);
115 void HTMLMarqueeElement::AfterSetAttr(int32_t aNameSpaceID
, nsAtom
* aName
,
116 const nsAttrValue
* aValue
,
117 const nsAttrValue
* aOldValue
,
118 nsIPrincipal
* aMaybeScriptedPrincipal
,
120 if (IsInComposedDoc() && aNameSpaceID
== kNameSpaceID_None
&&
121 aName
== nsGkAtoms::direction
) {
122 NotifyUAWidgetSetupOrChange();
124 return nsGenericHTMLElement::AfterSetAttr(
125 aNameSpaceID
, aName
, aValue
, aOldValue
, aMaybeScriptedPrincipal
, aNotify
);
128 void HTMLMarqueeElement::MapAttributesIntoRule(
129 MappedDeclarationsBuilder
& aBuilder
) {
130 nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder
);
131 nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder
);
132 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
133 nsGenericHTMLElement::MapBGColorInto(aBuilder
);
137 HTMLMarqueeElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
138 static const MappedAttributeEntry
* const map
[] = {
139 sImageMarginSizeAttributeMap
, sBackgroundColorAttributeMap
,
140 sCommonAttributeMap
};
141 return FindAttributeDependence(aAttribute
, map
);
144 nsMapRuleToAttributesFunc
HTMLMarqueeElement::GetAttributeMappingFunction()
146 return &MapAttributesIntoRule
;
149 void HTMLMarqueeElement::DispatchEventToShadowRoot(
150 const nsAString
& aEventTypeArg
) {
151 // Dispatch the event to the UA Widget Shadow Root, make it inaccessible to
153 RefPtr
<nsINode
> shadow
= GetShadowRoot();
155 RefPtr
<Event
> event
= new Event(shadow
, nullptr, nullptr);
156 event
->InitEvent(aEventTypeArg
, false, false);
157 event
->SetTrusted(true);
158 shadow
->DispatchEvent(*event
, IgnoreErrors());
161 void HTMLMarqueeElement::Start() {
162 if (GetShadowRoot()) {
163 DispatchEventToShadowRoot(u
"marquee-start"_ns
);
167 void HTMLMarqueeElement::Stop() {
168 if (GetShadowRoot()) {
169 DispatchEventToShadowRoot(u
"marquee-stop"_ns
);
173 } // namespace mozilla::dom