HTML - implement the labels attribute

This commit is contained in:
janekptacijarabaci 2017-08-18 06:04:15 +02:00 • committed by Roy Tam
commit 5b24f05ce7
25 changed files with 516 additions and 95 deletions

View file

@ -8800,6 +8800,16 @@ HTMLInputElement::GetWebkitEntries(nsTArray<RefPtr<FileSystemEntry>>& aSequence)
aSequence.AppendElements(mEntries);
}
already_AddRefed<nsINodeList>
HTMLInputElement::GetLabels()
{
if (!IsLabelable()) {
return nullptr;
}
return nsGenericHTMLElement::Labels();
}
} // namespace dom
} // namespace mozilla

View file

@ -704,6 +704,8 @@ public:
// XPCOM GetCustomVisibility() is OK
already_AddRefed<nsINodeList> GetLabels();
// XPCOM Select() is OK
Nullable<int32_t> GetSelectionStart(ErrorResult& aRv);

View file

@ -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<nsGenericHTMLElement*>(element);
}

View file

@ -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<nsINodeList>
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<nsLabelsNodeList> labels = slots->mLabelsList;
return labels.forget();
}
bool
nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
{

View file

@ -834,6 +834,12 @@ public:
}
virtual bool IsLabelable() const override;
static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData);
already_AddRefed<nsINodeList> Labels();
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);

View file

@ -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");
</script>
</pre>
</body>