From 6be9e507077bfdd2b8c82c203cf70f010ecce086 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Fri, 18 Aug 2017 06:04:15 +0200 Subject: HTML - implement the labels attribute --- dom/html/HTMLInputElement.cpp | 10 ++++++ dom/html/HTMLInputElement.h | 2 ++ dom/html/HTMLLabelElement.cpp | 23 ++++++++----- dom/html/nsGenericHTMLElement.cpp | 40 ++++++++++++++++++++++ dom/html/nsGenericHTMLElement.h | 6 ++++ .../forms/test_button_attributes_reflection.html | 9 +++-- 6 files changed, 79 insertions(+), 11 deletions(-) (limited to 'dom/html') diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 78f74ae0c..d46eccdbc 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -8800,6 +8800,16 @@ HTMLInputElement::GetWebkitEntries(nsTArray>& aSequence) aSequence.AppendElements(mEntries); } +already_AddRefed +HTMLInputElement::GetLabels() +{ + if (!IsLabelable()) { + return nullptr; + } + + return nsGenericHTMLElement::Labels(); +} + } // namespace dom } // namespace mozilla diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index e5d670e08..9ca876aee 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -704,6 +704,8 @@ public: // XPCOM GetCustomVisibility() is OK + already_AddRefed GetLabels(); + // XPCOM Select() is OK Nullable GetSelectionStart(ErrorResult& aRv); diff --git a/dom/html/HTMLLabelElement.cpp b/dom/html/HTMLLabelElement.cpp index c1d22b0a6..d1c037336 100644 --- a/dom/html/HTMLLabelElement.cpp +++ b/dom/html/HTMLLabelElement.cpp @@ -14,6 +14,7 @@ #include "nsFocusManager.h" #include "nsIDOMMouseEvent.h" #include "nsQueryObject.h" +#include "mozilla/dom/ShadowRoot.h" // construction, destruction @@ -268,17 +269,23 @@ HTMLLabelElement::GetLabeledElement() const return GetFirstLabelableDescendant(); } - // We have a @for. The id has to be linked to an element in the same document + // We have a @for. The id has to be linked to an element in the same tree // and this element should be a labelable form control. - //XXXsmaug It is unclear how this should work in case the element is in - // Shadow DOM. - // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=26365. - nsIDocument* doc = GetUncomposedDoc(); - if (!doc) { - return nullptr; + nsINode* root = SubtreeRoot(); + ShadowRoot* shadow = ShadowRoot::FromNode(root); + Element* element = nullptr; + + if (shadow) { + element = shadow->GetElementById(elementId); + } else { + nsIDocument* doc = GetUncomposedDoc(); + if (doc) { + element = doc->GetElementById(elementId); + } else { + element = nsContentUtils::MatchElementId(root->AsContent(), elementId); + } } - Element* element = doc->GetElementById(elementId); if (element && element->IsLabelable()) { return static_cast(element); } diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index d75001a83..2f890325a 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -108,6 +108,7 @@ #include "mozilla/StyleSetHandle.h" #include "mozilla/StyleSetHandleInlines.h" #include "ReferrerPolicy.h" +#include "mozilla/dom/HTMLLabelElement.h" using namespace mozilla; using namespace mozilla::dom; @@ -493,6 +494,14 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, } } + // We need to consider a labels element is moved to another subtree + // with different root, it needs to update labels list and its root + // as well. + nsDOMSlots* slots = GetExistingDOMSlots(); + if (slots && slots->mLabelsList) { + slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); + } + return rv; } @@ -513,6 +522,13 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent) } } + // We need to consider a labels element is removed from tree, + // it needs to update labels list and its root as well. + nsDOMSlots* slots = GetExistingDOMSlots(); + if (slots && slots->mLabelsList) { + slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); + } + nsStyledElement::UnbindFromTree(aDeep, aNullParent); } @@ -1701,6 +1717,30 @@ nsGenericHTMLElement::IsLabelable() const return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter); } +/* static */ bool +nsGenericHTMLElement::MatchLabelsElement(Element* aElement, int32_t aNamespaceID, + nsIAtom* aAtom, void* aData) +{ + HTMLLabelElement* element = HTMLLabelElement::FromContent(aElement); + return element && element->GetControl() == aData; +} + +already_AddRefed +nsGenericHTMLElement::Labels() +{ + MOZ_ASSERT(IsLabelable(), + "Labels() only allow labelable elements to use it."); + nsDOMSlots* slots = DOMSlots(); + + if (!slots->mLabelsList) { + slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement, + nullptr, this); + } + + RefPtr labels = slots->mLabelsList; + return labels.forget(); +} + bool nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const { diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 3cca41c3d..0635c27e1 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -834,6 +834,12 @@ public: } virtual bool IsLabelable() const override; + + static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID, + nsIAtom* aAtom, void* aData); + + already_AddRefed Labels(); + virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override; static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */); diff --git a/dom/html/test/forms/test_button_attributes_reflection.html b/dom/html/test/forms/test_button_attributes_reflection.html index 26858e939..4e702b3ac 100644 --- a/dom/html/test/forms/test_button_attributes_reflection.html +++ b/dom/html/test/forms/test_button_attributes_reflection.html @@ -128,9 +128,12 @@ is(typeof(document.createElement("button").setCustomValidity), "function", "button.setCustomValidity should be a function"); // .labels -todo("labels" in document.createElement("button"), - "button.labels isn't implemented yet"); - +ok("labels" in document.createElement("button"), + "button.labels should be an IDL attribute of the button element"); +is(typeof(document.createElement("button").labels), "object", + "button.labels should be an object"); +ok(document.createElement("button").labels instanceof NodeList, + "button.labels sohuld be an instance of NodeList"); -- cgit v1.2.3