2

This question has to do with the way selectors work and is not a problem I am having. I was working with some HTML similar to this:

<div class="example">
    <textarea>...</textarea>
    <textarea for="1">foo</textarea>
    <textarea for="2">bar</textarea>
    <textarea for="3">hello</textarea>
    <textarea for="4">world</textarea>
</div>

I was trying to use $('.example').children('textarea[for]:nth-of-type(1)') to select the first textarea with the for attribute. I kept getting undefined. I reread the documentation and noticed the line saying

Selects all elements that are the nth child of their parent in relation to siblings with the same element name.

And it makes sense that textarea[for]:nth-of-type(1) would be returning undefined because the first textarea doesn't have the for attribute.

My question then is, would it be possible in the future for an element[attribute]:nth-of-type(n) selector to return the nth element with the specified attribute? Would this require a whole new selector because of the way jQuery/CSS work?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
mcon
  • 679
  • 6
  • 22
  • *"would it be possible in the future for an `element[attribute]:nth-of-type(n)` selector to return the nth element with the specified attribute"* - No, because as you already pointed out, that's not how `:nth-of-type()` works. It's based on the element's tag **type**. You may already know this, but for the record you can just use the `:eq()` selector or `.eq()` method to get an element by its index *based on the set* of matching elements. In your case, `$('.example').children('textarea[for]:eq(0)')` - an index of `0` is used since `eq` is zero-based and `:nth-of-type` isn't, – Josh Crozier Dec 28 '15 at 19:14
  • @JoshCrozier I did in fact use the `:eq()` selector. So I guess a whole new selector would be required to do a nth-of-type-esque selection in conjunction with the attribute selector then? – mcon Dec 28 '15 at 19:30

3 Answers3

2

My question then is, would it be possible in the future for an element[attribute]:nth-of-type(n) selector to return the nth element with the specified attribute?

Not really, because the "type" in :nth-of-type() has a very specific meaning, and because it's not very intuitive for a simple selector to match an element based on any other criteria than the element's own characteristics as reflected in the DOM or similar.

Would this require a whole new selector because of the way jQuery/CSS work?

Yes, and this is why Selectors 4 introduced :nth-match(), which has since become an extension to the existing :nth-child(), that considers only a subset of elements according to a selector argument. See my answer to this question. In your case it would be

$('.example').children(':nth-child(1 of textarea[for])')

This is still not implemented anywhere; hopefully that will change in the new year.

Since this is jQuery, you can use :eq(0), but unless you will only have exactly one such .example and one such textarea, you may need to iterate the .example elements using .each() (thanks to how unintuitive these non-standard selectors are).

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • This is great, thanks! The whole `:nth-child(1 of textarea[for])` is kind of ugly in my opinion, but I'd have to deal with it I guess. Hopefully browser support will come around soon. – mcon Dec 29 '15 at 14:17
  • @mcon: I agree. Its only advantage is in being far more obvious in what it actually does. – BoltClock Jan 05 '16 at 07:13
0

nth-of-type use index from an actual DOM not from filtered list, so nth-of-type(1) will find you first textarea <textarea>...</textarea> but you filtered it by [for] ... nth-of-type(2) is <textarea for="1">foo</textarea>

nth-of-type(3) is <textarea for="2">bar</textarea> etc...

So answer is No, you can not use nth-of-type for this.

For getting first textarea child with "for" you can just use document.querySelector

var first = document.querySelector('.example > textarea[for]');
var first = document.querySelectorAll('.example > textarea[for]')[0];
//or jQuery
var first = $('.example > textarea[for]:eq(0)');

BTW in nth-of-type index starts from 1 not from 0...

h0x91B
  • 1,211
  • 15
  • 19
0

From my point of view, It is not a limitation, It is implemented well enough for patters.But not for your case (selecting single node), also we don't need it at all.

In your case you don't need to use the nth-type-of(n) since you are selecting single node not a set with some pattern like (odd , even , 2n+1)

For your case you can try the below one

 $('.example textarea[for]').first()

If you relay have a scenario to select set of node with nth-of-type(n). Yes it will work w/o any issues.

$('.example textarea[for]:nth-of-type(2n)')  This selector is working well enough.

see the demo > Run code Snippet

$(document).ready(function() {
  setTimeout(function() {
    $('.example textarea[for]:nth-of-type(2n)').css('background-color', 'red');
  }, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="example">
  <textarea>...</textarea>
  <textarea for="1">foo</textarea>
  <textarea for="2">bar</textarea>
  <textarea for="3">hello</textarea>
  <textarea for="4">world</textarea>
</div>