It surprised me that Sizzle (the selector engine jQuery uses) comes with a built-in :nth-child()
selector, but lacks an :nth-of-type()
selector.
To illustrate the difference between :nth-child()
and :nth-of-type()
and to illustrate the problem, consider the following HTML document:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>:nth-of-type() in Sizzle/jQuery?</title>
<style>
body p:nth-of-type(2n) { background: red; }
</style>
</head>
<body>
<p>The following CSS is applied to this document:</p>
<pre>body p:nth-of-type(2n) { background: red; }</pre>
<p>This is paragraph #1.</p>
<p>This is paragraph #2. (Should be matched.)</p>
<p>This is paragraph #3.</p>
<p>This is paragraph #4. (Should be matched.)</p>
<div>This is not a paragraph, but a <code>div</code>.</div>
<p>This is paragraph #5.</p>
<p>This is paragraph #6. (Should be matched.)</p>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script>
$(function() {
// The following should give every second paragraph (those that had red backgrounds already after the CSS was applied) an orange background.
// $('body p:nth-of-type(2n)').css('background', 'orange');
});
</script>
</body>
</html>
Since Sizzle uses the browser-native querySelector()
and querySelectorAll()
methods if those are present (i.e. in browsers that already implement the Selectors API), stuff like $('body p:nth-child');
will of course work. It won’t work in older browsers though, because Sizzle has no fallback method for this selector.
Is it possible to easily add the :nth-of-type()
selector to Sizzle, or to implement it in jQuery (by using the built-in :nth-child()
selector, perhaps)? A custom selector with parameters would be nice.
As a general rule, if you want to select an interval of a selector regardless of the type of element it is, use nth-child . However, if you want to select a specific type only and apply an interval selection from there, use nth-of-type .
To get the nth element of the same type, pass the :nth-of-type() pseudo-class as a parameter to the querySelector method, e.g. document. querySelector('#parent li:nth-of-type(2)') .
To get the nth-child of an element using the querySelector method, pass the :nth-child() pseudo-class as a parameter to the method, e.g. document. querySelector('#parent :nth-child(1)') . The nth-child pseudo-class returns the element that matches the specified position.
jQuery :nth-of-type() Selector The :nth-of-type(n) selector selects all elements that are the nth child, of a particular type, of their parent. Tip: Use the :nth-child() selector to select all elements that are the nth child, regardless of type, of their parent.
/**
* Return true to include current element
* Return false to exclude current element
*/
$.expr[':']['nth-of-type'] = function(elem, i, match) {
if (match[3].indexOf("n") === -1) return i + 1 == match[3];
var parts = match[3].split("+");
return (i + 1 - (parts[1] || 0)) % parseInt(parts[0], 10) === 0;
};
Test case - (check in IE or rename the selector)
You can of course add even & odd too:
match[3] = match[3] == "even" ? "2n" : match[3] == "odd" ? "2n+1" : match[3];
the jQuery plugin moreSelectors has support for nth-of-type (and many other selectors). I suggest either using that, or simply implement a simple plugin that only implements the exact selectors you need. You should be able to copy-paste code from there.
Happy hacking!
I can't pretend to know how nth-of-type is implemented, but jQuery does provide a mechanism by which you can create your own custom selector.
The following question deals with custom selectors, and may provide a useful insight to you
What useful custom jQuery selectors have you written?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With