最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is there a vanilla JS equivalent of jQuery .has()? - Stack Overflow

programmeradmin1浏览0评论

What would be the vanilla JS equivalent of :has in this jQuery selector?

$('.main-container').children('.analytics:has(a)').not('#promo')

Within .main-container, I'm trying to select all .analytics elements without an id of "promo" that contain <a> tags.

What I've tried:

document.querySelectorAll('.main-container .analytics:not(#promo)')

This will give me close to what I want, but I still have to filter out those .analytics parents that do NOT have <a> tags.

What would be the best way to approach this using vanilla JS?

What would be the vanilla JS equivalent of :has in this jQuery selector?

$('.main-container').children('.analytics:has(a)').not('#promo')

Within .main-container, I'm trying to select all .analytics elements without an id of "promo" that contain <a> tags.

What I've tried:

document.querySelectorAll('.main-container .analytics:not(#promo)')

This will give me close to what I want, but I still have to filter out those .analytics parents that do NOT have <a> tags.

What would be the best way to approach this using vanilla JS?

Share Improve this question asked Mar 20, 2018 at 20:11 asw1984asw1984 7631 gold badge7 silver badges19 bronze badges 3
  • it's not an exact match but you could try the contains method – Jonathan Chaplin Commented Mar 20, 2018 at 20:16
  • How about looping throught the results of the querySelectorAll and only apply the rules where this.getElementsByTagName('a').length > 0? – Balázs Varga Commented Mar 20, 2018 at 20:17
  • Is it not an easier way to select by using classes? – axdrv Commented Nov 24, 2021 at 9:01
Add a comment  | 

4 Answers 4

Reset to default 10
  1. Query the document for using your desired selector, in this case: .analytics:not(#promo)
  2. Convert the NodeList to an Array
  3. Filter the array using the predicate: element => element.querySelector('your-selector')

element.querySelector('your-selector') will evaluate to null (which is falsey) if no child element is found

Generally as a function

function has(nodeList, selector) {
  return Array.from(nodeList).filter(e => e.querySelector(selector))
}

const nodeList = document.querySelectorAll('.main-container > .analytics:not(#promo)')

has(nodeList, 'a').forEach(e => e.style.background = "red")
<div class="main-container">
  <div class="analytics">
    <a>Should be red</a>
  </div>
  <div class="analytics">
    Should not be red
  </div>
  <div id="promo" class="analytics">
    <a>Should not be red</a>
  </div>
</div>

As a NodeList.prototype

NodeList.prototype.has = function(selector) {
  return Array.from(this).filter(e => e.querySelector(selector))
}

document
  .querySelectorAll('.main-container > .analytics:not(#promo)')
  .has('a')
  .forEach(e => e.style.background = 'red')
<div class="main-container">
  <div class="analytics">
    <a>Should be red</a>
  </div>
  <div class="analytics">
    Should not be red
  </div>
  <div id="promo" class="analytics">
    <a>Should not be red</a>
  </div>
</div>

You could select the <a> and then get their parentNodes:

var a = document.querySelectorAll('.main-container .analytics:not(#promo) a');
var yourElements = [];
for (var i = 0; i < a.length; i++) {
  yourElements.push(a[i].parentNode);
}

yourElements.forEach(e => e.style.background = "red");
<div class="main-container">
  <div class="analytics">
    <a>Should be red</a>
  </div>
  <div class="analytics">
    Should not be red
  </div>
  <div id="promo" class="analytics">
    <a>Schould not be red</a>
  </div>
</div>

EDIT: just noticed this only works if the <a> is a direct child of your wanted element.

There is no equivalent selector for :has, you'll have to use an initial selection and then filter them

var el = document.querySelectorAll('.main-container > .analytics:not(#promo)');
var res = [];
for (let x = 0; x < el.length; x++){
    if (el[x].querySelector('a')) res.push(el[x]);
}
//res has has the array of elements needed.

Josh Larson's polyfill-css-has provides a querySelectorAllWithHas method based on vanilla JavaScript.

发布评论

评论列表(0)

  1. 暂无评论