简体   繁体   中英

querySelector to select the closest parent for h1 and p+p elements - is it possible?

EDIT The structure is unknown - it should work for any news site, where there is a container/wrapper, that contains h1 and p+p (everything related to the main article of that page)

What I want can also be achieved with

let story = document.querySelector('p+p').parentElement;
while(!story.querySelector('h1')){
    story = story.parentElement;
}
console.log(story);

But I'm wondersing if there's a better solution?

Every news article has h1 tag and paragraphs with text. I'm wondering if it's possible to write a querySelector that will select the closest parent/container element that contains both h1 and p+p . The trick is that it should work with any news website...


when I write

document.body.querySelector('* h1')

I can get h1 container, but there's might be multiple h1 tags on the page according to HTML5

I know about querySelectorAll but this will not help in my case


when I write

document.body.querySelector('* p+p').parentElement

I can get container for article body with paragraphs of text


My question is if it's possible to combine those two examples into a single query? (w/o loop and multiple querys) Something like...

document.body.querySelector('* ~ h1 ~ p+p')
document.body.querySelector('* h1 p+p')

...but workable 😅

I created a jQuery solution.

Stack Snippet

 $('.block').each(function(e) { if ($(this).find('h4').length > 0 && $(this).find('p+p').length > 0) { console.log('block ' + (e + 1)) } }); 
 body { font: 13px Verdana; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="block vv"> <h4>heading</h4> <p>para1</p> <p>para2</p> </div> <div class="block"> <h4>heading</h4> <p>para1</p> </div> <div class="block"> <h4>heading</h4> <p>para1</p> <p>para2</p> </div> 

I hope this will help you!

My question is if it's possible to combine those two examples into a single query?

tl;dr: No, it's not. Certainly not today, and probably not anytime soon. If you're not interested in anything beyond a practical answer, this is all you need to know; everything past this paragraph is background information pertaining to a feature that doesn't exist in the standard yet.


It depends on what you mean by "a single query". Do you mean "a single assignment"? If so, the :has() pseudo-class from jQuery , slated for standardization in Selectors 4 , will help tremendously:

// In jQuery: $('p+p').closest(':has(h1)')
let story = document.querySelector('p+p').closest(':has(h1)');

But notice that it's used in conjunction with Element#closest() , and furthermore, :has() is not supported natively yet, and there are no plans to implement it in any browser in the near future. So if jQuery is not an option, what you have is the best you've got for a long while.

If by "a single query" you mean "a single selector", then the answer is no, because it's not possible to write a selector matching the closest common ancestor of two or more descendants. The closest would be :has(h1):has(p+p) , but that will match every such ancestor, starting with the innermost of these and leading all the way up to the root element. There is no selector for matching just the innermost of these.

Based on the website you provided just use a child and sibling selector. The following will work.:

window.document.querySelector("*>h1, * p+p").parentNode

It selects all elements with an h1 and all elements with multiple p tags. I tried it onthe page you provided and it produced the same result as your JS code.

A few additional notes, since you didn't specify jquery I gave you a JavaScript solution. Currently there is no parent selector or querySelector so parentNode is the closest thing to that. Lastly, your original solution specified article (and not div like the page has). If you want that, just swap out div for article.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM