Closed Outrovurt closed 1 month ago
Hi thanks for the issue @Outrovurt, the child
and children
naming was not the best, and these fns therefore have been recently deprecated, see https://github.com/clj-commons/etaoin/issues/559#issuecomment-2248599808. New names are: query-from
and query-all-from
.
This change will be in the next release of Etaoin.
Does that help?
Hi Lee,
dgr's comment that you linked to is spot on in his analysis. So can you confirm what changes which impact this issue will be in the next release and how it will work? Specifically if I want to write a query to return just the immediate children, how would I do that? From what you have written, it sounds like you are just renaming child
-> query-from
and children
-> query-all-from
, is that correct? Or are you additionally going to create new child
and children
functions which do what they are supposed to?
Hi @Outrovurt, we have no plans to implement new child
and children
; the existing fns will remain to avoid a breaking change but will be deprecated.
I'll fire up a REPL and see if I can answer your question about immediate children.
Let's set things up:
(require '[etaoin.api :as e])
(def driver (e/firefox))
And then navigate somewhere interesting:
(e/go driver "https://clojure.org")
I did a page inspection in Firefox and saw a div
with the class
clj-learn-more
.
Let's see if we can query its immediate children.
We'll use the :outerHTML
property to see if we were successful.
Let's start with XPath, ./*
is immediate children of:
(for [el (e/query-all driver {:fn/has-class "clj-learn-more"} "./*")]
(e/get-element-property-el driver el :outerHTML))
;; => ("<h3 class=\"clj-learn-more-heading\">Learn More</h3>"
;; "<a href=\"about/rationale\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Rationale</h4>\n <p class=\"clj-learn-more-detail\">A brief overview of Clojure and the features it includes</p></a>"
;; "<a href=\"guides/getting_started\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Getting Started</h4>\n <p class=\"clj-learn-more-detail\">Resources for getting Clojure up and running</p></a>"
;; "<a href=\"reference/documentation\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Reference</h4>\n <p class=\"clj-learn-more-detail\">Grand tour of all that Clojure has to offer</p></a>"
;; "<a href=\"guides/guides\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Guides</h4>\n <p class=\"clj-learn-more-detail\">Walkthroughs to help you learn along the way</p></a>"
;; "<a href=\"community/resources\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Community</h4>\n <p class=\"clj-learn-more-detail\">We have a vibrant, flourishing community. Join us!</p></a>"
;; "<a href=\"https://www.youtube.com/user/ClojureTV/videos\"><img src=\"/images/clojuretv.png\" alt=\"Clojure TV logo\"></a>")
But maybe you are more familiar with CSS. I had to look this one up, but the equivalent is :scope > *
:
(for [el (e/query-all driver {:fn/has-class "clj-learn-more"} {:css ":scope > *"})]
(e/get-element-property-el driver el :outerHTML))
;; => ("<h3 class=\"clj-learn-more-heading\">Learn More</h3>"
;; "<a href=\"about/rationale\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Rationale</h4>\n <p class=\"clj-learn-more-detail\">A brief overview of Clojure and the features it includes</p></a>"
;; "<a href=\"guides/getting_started\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Getting Started</h4>\n <p class=\"clj-learn-more-detail\">Resources for getting Clojure up and running</p></a>"
;; "<a href=\"reference/documentation\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Reference</h4>\n <p class=\"clj-learn-more-detail\">Grand tour of all that Clojure has to offer</p></a>"
;; "<a href=\"guides/guides\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Guides</h4>\n <p class=\"clj-learn-more-detail\">Walkthroughs to help you learn along the way</p></a>"
;; "<a href=\"community/resources\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Community</h4>\n <p class=\"clj-learn-more-detail\">We have a vibrant, flourishing community. Join us!</p></a>"
;; "<a href=\"https://www.youtube.com/user/ClojureTV/videos\"><img src=\"/images/clojuretv.png\" alt=\"Clojure TV logo\"></a>")
Or if we want to express our query entirely in CSS (this is probably clearer):
(for [el (e/query-all driver {:css ".clj-learn-more > *"})]
(e/get-element-property-el driver el :outerHTML))
;; => ("<h3 class=\"clj-learn-more-heading\">Learn More</h3>"
;; "<a href=\"about/rationale\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Rationale</h4>\n <p class=\"clj-learn-more-detail\">A brief overview of Clojure and the features it includes</p></a>"
;; "<a href=\"guides/getting_started\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Getting Started</h4>\n <p class=\"clj-learn-more-detail\">Resources for getting Clojure up and running</p></a>"
;; "<a href=\"reference/documentation\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Reference</h4>\n <p class=\"clj-learn-more-detail\">Grand tour of all that Clojure has to offer</p></a>"
;; "<a href=\"guides/guides\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Guides</h4>\n <p class=\"clj-learn-more-detail\">Walkthroughs to help you learn along the way</p></a>"
;; "<a href=\"community/resources\" class=\"w-inline-block clj-learn-more-item\">\n <h4 class=\"clj-learn-more-item-heading\">Community</h4>\n <p class=\"clj-learn-more-detail\">We have a vibrant, flourishing community. Join us!</p></a>"
;; "<a href=\"https://www.youtube.com/user/ClojureTV/videos\"><img src=\"/images/clojuretv.png\" alt=\"Clojure TV logo\"></a>")
So, Etaoin queries already support restricting elements to immediate children, so we don't need any specialized fns. Does that help?
Aha, so just use the XPath or CSS queries, no special functions. Got it, thanks a lot Lee.
My pleasure @Outrovurt, I'm sure your question will help someone else down the line.
Version 0.4.6
Platform Operating System: Arch Linux Clojure version: 1.11.1
Browser vendor: chrome
Symptom Ok, this is part bug, part feature request: the
children
function should return immediate child elements only, however it actually returns any matching descendant. It's true, the docs aren't that specific, but in CSS queries we make the distinction between children (immediate) and descendants. I feel we should do the same with etaoin. That said, changing the functionality ofchildren
is a breaking change, so it would probably make more sense to introducedescendants
, and alias tochildren
, and perhapsimmediate-children
ordirect-children
. But a separate function to the existingchildren
is definitely a good idea.Reproduction
This will return all
<li>
elements, not just immediate children oful-element
.Actual behavior See above.
Expected behavior See above.
Diagnosis See above.
Action This is open to discussion, please let me know your thoughts on the matter. If something else exists which does this already, also let me know. Thanks.