0

Cannot get the last element with specific class or attribute using querySelector.

My Current Code:

<div id="wrapper">
    <div class="abc" db="box"></div>
    <div class="abc" db="box"></div>
    <div class="abc" db="box"></div>
    <div class="def"></div>
    <div class="abc" db="box"></div>
    <div class="ghi"></div>
    <div class="abc" db="box"></div>
    <div class="ghi"></div>
    <div class="ghi"></div>
</div>
<script>
    console.log(document.querySelector('#wrapper>[db="box"]:last-child')); // showing null
    console.log(document.querySelector('#wrapper>div.abc:last-child')); // showing null
</script>

I've found some solutions like:

const elements = document.querySelectorAll('#wrapper>div.abc');
console.log(elements[elements.length - 1]);

The above code works but it gets all of the elements first and then retrieves the last one from it.

document.querySelector('#wrapper>[db="box"]:last-child')

If anyone could make the above query correct then it will search for the last one only.

  • 1
    last child is only if it is the last element.... – epascarello Mar 17 '23 at 16:55
  • https://stackoverflow.com/questions/7298057/how-can-i-select-the-last-element-with-a-specific-class-not-last-child-inside-o – epascarello Mar 17 '23 at 16:55
  • 3
    The `length - 1` solution you've listed is fine, why do you want to avoid it? – DBS Mar 17 '23 at 16:55
  • 1
    Not possible using CSS native selectors. Just bite the bullet and select 'em all. Your next line of thinking will be, ooh, what about `:last-of-type`? That won't work either, for reasons yonder: https://stackoverflow.com/questions/13554552/why-does-classlast-of-type-not-work-as-i-expect – Leland Mar 17 '23 at 16:58
  • @Leland I've already tried the `:last-of-type` bro! but I forgot to mention it in the question. – Abdul Raheem Dumrai Mar 17 '23 at 17:12
  • @Leland Can you explain why it's not possible or can you refer me a link? – Abdul Raheem Dumrai Mar 17 '23 at 20:01
  • 1
    I already have :) Read the answers in that link - "there is no selector for the last instance of a class" – Leland Mar 17 '23 at 21:01
  • @DBS I had already provided the reason in the question **If anyone could make the above query correct then it will search for the last one only.** – Abdul Raheem Dumrai Mar 18 '23 at 07:14
  • 1
    That doesn't explain **why** you don't want to use it, but I assume what you are implying is that you think it will affect performance? If that is the case, you probably don't need to worry about it, it's very unlikely there will be any measurable performance impact from that approach. – DBS Mar 18 '23 at 09:02

1 Answers1

1

If CSS selectors are not powerful enough for your requirement, consider using expressions like in this example:

console.log(
  document.evaluate(`//*[@id='wrapper']
    /*[@db='box' and
    not(following-sibling::*/@db='box')]`,
    document, () => {},
    XPathResult.FIRST_ORDERED_NODE_TYPE
  ).singleNodeValue
);
<div id="wrapper">
  <div class="abc" db="box"></div>
  <div class="abc" db="box"></div>
  <div class="abc" db="box"></div>
  <div class="def"></div>
  <div class="abc" db="box"></div>
  <div class="ghi"></div>
  <div class="abc" db="box"></div>
  <div class="ghi"></div>
  <div class="ghi"></div>
</div>

Only the last matching element is selected, all earlier ones are ruled out by the condition not(following-sibling::*/@db='box')].

Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31