James Kyle
James Kyle

Reputation: 4178

How to add nth-item classes with jQuery

http://jsfiddle.net/JamesKyle/y7hBQ/

I'm making a simple jquery counting function that adds the following classes:

  1. First & Last
  2. Even & Odd
  3. nth-item-# (counts in order)
  4. 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

Answers (4)

Emre Erkan
Emre Erkan

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

Rob W
Rob W

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

Ray Perea
Ray Perea

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

simshaun
simshaun

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) );
        });
    });
});

jsFiddle

Upvotes: 1

Related Questions