Reputation: 4178
I'm making a simple jquery counting function that adds the following classes:
- First & Last
- Even & Odd
- nth-item-# (counts in order)
- nth-item--# (counts backwards)
I have the first two done pretty easily, but the second two are giving me trouble since I'm new to jQuery/Javascript
You can see the jsfiddle here: http://jsfiddle.net/JamesKyle/y7hBQ/
This is the code I'm currently using:
$(document).ready(function() {
$('.count, ul').each(function() {
var countChildren = $(this).children();
$(countChildren).filter(':even').addClass('even');
$(countChildren).filter(':odd').addClass('odd');
$(countChildren).first().addClass('first');
$(countChildren).last().addClass('last');
var numberOfChildren = $(countChildren).size();
// $(countChildren).addClass('nth-item-' + #);
// ⬆
// Fill with the elements number
// $(countChildren).addClass('nth-item--' + #);
// ⬆
// Fill with the elements number (negative count)
});
});
I'm only focusing on the commented out lines
Again here is the jsfiddle: http://jsfiddle.net/JamesKyle/y7hBQ/
Thanks ahead of time!
UPDATE :
I have two solutions below, I plan to use this on a very large scale so if you could recommend what would be the most efficient way it would help me a lot! Thanks!!
Upvotes: 2
Views: 790
Reputation: 8482
If every effiency count then you should consider reduce iterations;
$('.count, ul').each(function() {
var $children = $(this).children(),
count = $children.size(),
$item;
$children.each(function(i) {
$item = $(this)
.addClass(i % 2 === 0 ? 'even' : 'odd')
.addClass('nth-item-' + (i + 1))
.addClass('nth-item--' + (count - i));
if (i === 0) {
$item.addClass('first');
}
if (i == count - 1) {
$item.addClass('last');
}
});
});
This way you iterate on children only one time. When you use filters, it iterates and filters items according to your filter. jsFiddle here.
A little benchmark is here.
Upvotes: 1
Reputation: 349032
Edit: See this fiddle for a pure CSS solution. It doesn't require any JavaScript (using the :nth-child
selector).
Use the .index()
method to get the index of the current element at a collection of elements. Also, since .children()
returns a jQuery object, it's unnecessary to wrap countChildren
in a $
.
For clarification, the code below is using indexes starting at 1 and -1 (as hinted at your CSS code).
Demo: http://jsfiddle.net/y7hBQ/18/
$(document).ready(function() {
$('.count, ul').each(function() {
var countChildren = $(this).children();
countChildren.filter(':even').addClass('even');
countChildren.filter(':odd').addClass('odd');
countChildren.first().addClass('first');
countChildren.last().addClass('last');
var numberOfChildren = countChildren.size();
countChildren.each(function(i){
var posindex = countChildren.index(this) + 1,
//^ This can be replaced by i + 1, for efficiency
negindex = numberOfChildren - posindex + 1;
$(this).addClass('nth-item-' + posindex)
.addClass('nth-item--' + negindex);
});
});
});
Upvotes: 3
Reputation: 5851
I think what you are looking for is:
var count = countChildren.length;
countChildren.each(function(index) {
$(this).addClass('nth-item-'+index);
.addClass('nth-item--'+(count-1-index));
});
There may be a faster way to do this, but.... hope this works for you.
Upvotes: 1
Reputation: 21466
If I understand correctly, this:
$(document).ready(function() {
$('.count, ul').each(function() {
var countChildren = $(this).children();
countChildren.filter(':even').addClass('even');
countChildren.filter(':odd').addClass('odd');
countChildren.first().addClass('first');
countChildren.last().addClass('last');
var numberOfChildren = countChildren.size();
countChildren.each(function(i) {
$(this).addClass('nth-item-' + (i + 1) )
.addClass('nth-item--' + (numberOfChildren - i) );
});
});
});
Upvotes: 1