Проверьте, существует ли класс где-то в родительском - vanilla JS
Я действительно пытаюсь понять, как это сделать. Я хочу проверить, если класс exesits где-то в одном из родительских элементов элемента.
Я не хочу использовать какую-либо библиотеку, просто ваниль JS.
В приведенных ниже примерах он должен возвращать значение true, если рассматриваемый элемент находится где-то в дочерних элементах элемента с "классом" в качестве имени класса.
Я думаю, что это будет что-то вроде этого с jQuery:
if( $('#the-element').parents().hasClass('the-class') ) {
return true;
}
Итак, это возвращает true:
<div>
<div class="the-class">
<div id="the-element"></div>
</div>
</div>
Так делает это:
<div class="the-class">
<div>
<div id="the-element"></div>
</div>
</div>
... но это возвращает false:
<div>
<div class="the-class">
</div>
<div id="the-element"></div>
</div>
Ответы
Ответ 1
Вам нужно будет сделать это рекурсивно:
// returns true if the element or one of its parents has the class classname
function hasSomeParentTheClass(element, classname) {
if (element.className.split(' ').indexOf(classname)>=0) return true;
return element.parentNode && hasSomeParentTheClass(element.parentNode, classname);
}
Демонстрация (откройте консоль, чтобы увидеть true
)
Ответ 2
fiddle
Код
function hasClass(element, className) {
var regex = new RegExp('\\b' + className + '\\b');
do {
if (regex.exec(element.className)) {
return true;
}
element = element.parentNode;
} while (element);
return false;
}
ИЛИ
function hasClass(element, className) {
do {
if (element.classList && element.classList.contains(className)) {
return true;
}
element = element.parentNode;
} while (element);
return false;
}
Ответ 3
Вы можете использовать some
и contains
для достижения результата:
function hasParentWithMatchingSelector (target, selector) {
return [...document.querySelectorAll(selector)].some(el =>
el !== target && el.contains(target)
)
}
// usage
hasParentWithMatchingSelector(myElement, '.some-class-name');
Ответ 4
Я в порядке с функцией, которую Denys Séguret опубликовал, выглядит элегантно, и мне это нравится.
Я немного изменил эту функцию, поскольку, если класс, указанный в параметре, отсутствует во всей DOM, он терпит неудачу, когда рекурсия достигает объекта документа, потому что это правда, что мы управляем, если элемент имеет родительский node ( в последней строке, а когда документ является элементом, родительский node имеет значение NULL), но перед тем, как мы выполним предыдущую строку, а когда этот элемент является документом, document.className
- undefined
, и он не работает, поэтому элемент управления должен быть перемещен в верхнюю часть.
function hasSomeParentTheClass(element, classname) {
//
// If we are here we didn't find the searched class in any parents node
//
if (!element.parentNode) return false;
//
// If the current node has the class return true, otherwise we will search
// it in the parent node
//
if (element.className.split(' ').indexOf(classname)>=0) return true;
return hasSomeParentTheClass(element.parentNode, classname);
}
Ответ 5
Я считаю, if( $('#the-element').parents('.the-class').length )
быть более эффективным, но, возможно, не таким, как читаемый человеком; который с querySelector
на картинке может быть заменен следующим образом:
function hasParent(element, parentSelector) {
var potentialParents = document.querySelectorAll(parentSelector);
for(i in potentialParents) if(potentialParents[i].contains(element))
return potentialParents[i];
return false;
}
Это даст вам возможность:
var elm = document.getElementById('the-element');
if(hasParent(elm, '.the-class')) return true;
Ответ 6
Вы можете использовать метод closest()
Element
, который пересекает родительские элементы (направляясь к корню документа) Элемента, пока не найдет узел, который соответствует предоставленной строке selectorString. Вернет себя или соответствующего предка. Если такого элемента не существует, возвращается ноль.
Вы можете преобразовать возвращаемое значение в логическое значение
const el = document.getElementById('div-03');
const r1 = el.closest("#div-02");
console.log(Boolean(r1));
// returns the element with the id=div-02
const r2 = el.closest("#div-not-exists");
console.log(Boolean(r2));
<article>
<div id="div-01">Here is div-01
<div id="div-02">Here is div-02
<div id="div-03">Here is div-03</div>
</div>
</div>
</article>
Ответ 7
Мой пример для Vanilla JS, он использует ванильный эквивалент parents()
из jQuery
var htmlElement = <htmlElement>,
parents = [],
classExist;
while (htmlElement = htmlElement.parentNode.closest(<parentSelector>)) {
parents.push(htmlElement);
}
classExist = (parents > 0);
Итак, ваш селектор должен быть .className
И просто проверьте, является ли родительский > 0
Ответ 8
Еще одна альтернатива для тех, кто любит этот стиль для современных/многозадачных браузеров.
const hasClass = (element, className) => {
return element.classList.contains(className);
};
const hasParent = (element, className) => {
if (!element.parentNode) {
return false;
}
if (hasClass(element, className)) {
return true;
}
return hasParent(element.parentNode, className)
};
Рабочая демонстрация:
const hasClass = (element, className) => {
return element.classList.contains(className);
};
const hasParent = (element, className) => {
if (!element.parentNode) {
return false;
}
if (hasClass(element, className)) {
return true;
}
return hasParent(element.parentNode, className)
};
/* Demo Code, can ignore */
const child = document.getElementById('child');
const orphan = document.getElementById('orphan');
const output = document.getElementById('output');
const log = 'child has parent? ${hasParent(child, 'list')}
orphan has parent? ${hasParent(orphan, 'list')}
'
output.innerText = log;
#output {
margin-top: 50px;
background: black;
color: red;
padding: 20px;
}
<div>
<ul class="list">
<li>
<a id="child" href="#">i have a parent</a>
</li>
</ul>
</div>
<div>
<ul>
<li>
<a id="orphan" href="#">im an orphan</a>
</li>
</ul>
</div>
<div id="output"></div>
Ответ 9
я написал маленький отрывок, чтобы пройти через DOM, чтобы найти первый соответствующий parentNode.
Надеюсь, это когда-нибудь кому-нибудь поможет.
(/¯◡ ‿ ◡) ⊃━ ☆ ゚. * ・。 ゚,
function getFirstParentMatch(element, selector) {
if (!element) {return element};
element.matches(selector) || (element = (element.nodeName.toLowerCase() === 'html' ? false : getFirstParent(element.parentNode, selector)));
return element;
}
Ответ 10
Поскольку идентификатор должен быть уникальным в контексте документа, вы можете просто использовать вместо него:
return !!document.querySelector('.the-class #the-element');
Если вы хотите включить сам элемент, вы можете использовать:
return !!document.querySelector('.the-class #the-element, #the-element.the-class');