Bug 1403871 Part 1: Add getElementsWithFlex and getElementsWithGrid to Element.
MozReview-Commit-ID: L44Q95wEqDA
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1572,16 +1572,74 @@ Element::HasAttributeNS(const nsAString&
}
already_AddRefed<nsIHTMLCollection>
Element::GetElementsByClassName(const nsAString& aClassNames)
{
return nsContentUtils::GetElementsByClassName(this, aClassNames);
}
+void
+Element::GetElementsWithFlex(nsTArray<RefPtr<Element>>& aElements)
+{
+ // This helper function is passed to GetElementsByMatching()
+ // to identify elements with styling which will cause them to
+ // generate a nsFlexContainerFrame during layout.
+ auto IsDisplayFlex = [](Element* aElement) -> bool
+ {
+ // Check the display style for something that will resolve to flex.
+ RefPtr<nsStyleContext> styleContext =
+ nsComputedDOMStyle::GetStyleContext(aElement, nullptr, nullptr);
+ if (styleContext) {
+ const nsStyleDisplay* display = styleContext->StyleDisplay();
+ return (display->mDisplay == StyleDisplay::Flex ||
+ display->mDisplay == StyleDisplay::InlineFlex ||
+ display->mDisplay == StyleDisplay::WebkitBox ||
+ display->mDisplay == StyleDisplay::WebkitInlineBox);
+ }
+ return false;
+ };
+
+ GetElementsByMatching(IsDisplayFlex, aElements);
+}
+
+void
+Element::GetElementsWithGrid(nsTArray<RefPtr<Element>>& aElements)
+{
+ // This helper function is passed to GetElementsByMatching()
+ // to identify elements with styling which will cause them to
+ // generate a nsGridContainerFrame during layout.
+ auto IsDisplayGrid = [](Element* aElement) -> bool
+ {
+ // Check the display style for something that will resolve to grid.
+ RefPtr<nsStyleContext> styleContext =
+ nsComputedDOMStyle::GetStyleContext(aElement, nullptr, nullptr);
+ if (styleContext) {
+ const nsStyleDisplay* display = styleContext->StyleDisplay();
+ return (display->mDisplay == StyleDisplay::Grid ||
+ display->mDisplay == StyleDisplay::InlineGrid);
+ }
+ return false;
+ };
+
+ GetElementsByMatching(IsDisplayGrid, aElements);
+}
+
+void
+Element::GetElementsByMatching(nsElementMatchFunc aFunc,
+ nsTArray<RefPtr<Element>>& aElements)
+{
+ for (nsINode* cur = this; cur; cur = cur->GetNextNode(this)) {
+ if (cur->IsElement() && aFunc(cur->AsElement())) {
+ aElements.AppendElement(cur->AsElement());
+ }
+ }
+}
+
+
/**
* Returns the count of descendants (inclusive of aContent) in
* the uncomposed document that are explicitly set as editable.
*/
static uint32_t
EditableInclusiveDescendantCount(nsIContent* aContent)
{
auto htmlElem = nsGenericHTMLElement::FromContent(aContent);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -979,18 +979,44 @@ public:
void SetPseudoElementType(CSSPseudoElementType aPseudo) {
static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
"Need to be able to store this in a void*");
MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
}
+ /**
+ * Return an array of all elements and descendants, starting with
+ * this, that have styling which will cause them to generate
+ * a nsFlexContainerFrame during layout. This covers elements
+ * that are not visible, but does not include pseudo-elements.
+ */
+ void GetElementsWithFlex(nsTArray<RefPtr<Element>>& aElements);
+
+ /**
+ * Return an array of all elements and descendants, starting with
+ * this, that have styling which will cause them to generate
+ * a nsGridContainerFrame during layout. This covers elements
+ * that are not visible, but does not include pseudo-elements.
+ */
+ void GetElementsWithGrid(nsTArray<RefPtr<Element>>& aElements);
+
private:
/**
+ * Define a general matching function that can be passed to
+ * GetElementsByMatching(). Each Element being considered is
+ * passed in.
+ */
+ typedef bool (*nsElementMatchFunc)(Element* aElement);
+
+ void GetElementsByMatching(nsElementMatchFunc aFunc,
+ nsTArray<RefPtr<Element>>& aElements);
+
+ /**
* Implement the algorithm specified at
* https://dom.spec.whatwg.org/#insert-adjacent for both
* |insertAdjacentElement()| and |insertAdjacentText()| APIs.
*/
nsINode* InsertAdjacent(const nsAString& aWhere,
nsINode* aNode,
ErrorResult& aError);
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -64,16 +64,20 @@ interface Element : Node {
boolean webkitMatchesSelector(DOMString selector);
[Pure]
HTMLCollection getElementsByTagName(DOMString localName);
[Throws, Pure]
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
[Pure]
HTMLCollection getElementsByClassName(DOMString classNames);
+ [ChromeOnly, Pure]
+ sequence<Element> getElementsWithFlex();
+ [ChromeOnly, Pure]
+ sequence<Element> getElementsWithGrid();
[CEReactions, Throws, Pure]
Element? insertAdjacentElement(DOMString where, Element element); // historical
[Throws]
void insertAdjacentText(DOMString where, DOMString data); // historical
/**