querySelector для выбора ближайшего родителя для элементов h1 и p+p - возможно ли это?
РЕДАКТИРОВАТЬ Структура неизвестна - она должна работать для любого новостного сайта, где есть контейнер / оболочка, которая содержит h1 и p+p (все, что связано с основной статьей этой страницы)
То, что я хочу, также может быть достигнуто с
let story = document.querySelector('p+p').parentElement;
while(!story.querySelector('h1')){
story = story.parentElement;
}
console.log(story);
Но мне интересно, есть ли лучшее решение?
Каждая новостная статья имеет тег h1 и параграфы с текстом. Мне интересно, можно ли написать querySelector, который выберет ближайший родительский / контейнерный элемент, который содержит h1 и p + p. Хитрость в том, что он должен работать с любым новостным сайтом...
когда я пишу
document.body.querySelector('* h1')
Я могу получить контейнер h1, но на странице может быть несколько тегов h1 в соответствии с HTML5
Я знаю о querySelectorAll, но это не поможет в моем случае
когда я пишу
document.body.querySelector('* p+p').parentElement
Я могу получить контейнер для тела статьи с абзацами текста
Мой вопрос: возможно ли объединить эти два примера в один запрос? (без цикла и нескольких запросов) Что-то вроде...
document.body.querySelector('* ~ h1 ~ p+p')
document.body.querySelector('* h1 p+p')
... но работоспособный
3 ответа
Мой вопрос: возможно ли объединить эти два примера в один запрос?
ДЛ: Нет, это не так. Конечно, не сегодня, и, вероятно, не в ближайшее время. Если вас не интересует что-то кроме практического ответа, это все, что вам нужно знать; все, что за этим абзацем, является справочной информацией, относящейся к функции, которой еще нет в стандарте.
Это зависит от того, что вы подразумеваете под "одним запросом". Вы имеете в виду "одно назначение"? Если так, то :has()
Псевдокласс от jQuery, предназначенный для стандартизации в Selectors 4, очень поможет:
// In jQuery: $('p+p').closest(':has(h1)')
let story = document.querySelector('p+p').closest(':has(h1)');
Но обратите внимание, что он используется в сочетании с Element#closest()
, и, кроме того, :has()
пока не поддерживается изначально, и в ближайшем будущем не планируется внедрять его в любом браузере. Так что, если JQuery не вариант, то у вас есть лучшее, что у вас есть в течение длительного времени.
Если под "одним запросом" вы подразумеваете "один селектор", то ответ "нет", потому что невозможно написать селектор, соответствующий ближайшему общему предку двух или более потомков. Ближайшим будет :has(h1):has(p+p)
, но это будет соответствовать каждому такому предку, начиная с самого внутреннего из них и вплоть до корневого элемента. Не существует селектора для сопоставления только самых внутренних из них.
Я создал решение JQuery.
Фрагмент стека
$('.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>
Я надеюсь, что это поможет вам!
Основываясь на сайте, который вы предоставили, просто используйте выбор ребенка и родного брата. Следующее будет работать.
window.document.querySelector("*>h1, * p+p").parentNode
Он выбирает все элементы с h1 и все элементы с несколькими тегами p. Я попробовал это на странице, которую вы предоставили, и это дало тот же результат, что и ваш код JS.
Несколько дополнительных замечаний, поскольку вы не указали jquery, я дал вам решение на JavaScript. В настоящее время нет родительского селектора или querySelector, поэтому parentNode является наиболее близким к этому. Наконец, ваше оригинальное решение указало статью (а не div, как на странице). Если вы хотите этого, просто поменяйте местами div для статьи.