kthornbloom
kthornbloom

Reputation: 3730

Select next element via class with jQuery one at a time

Backstory: I have HTML that's been searched for a phrase, which puts a span around each instance. So if I search for Lorem, every place that word appears, it will look like this:

<span class="live-search-highlight">Lorem</span>

Which gives it a little highlight.The very first instace is given a different class with a more distinct highlight like this:

<span class="highlight-current">Lorem</span>

Question: I want to click a button, and starting at .highlight-current, I want to find the next instance of .live-search-highlight and switch its class to .highlight-current. How can I achieve this with jQuery? Here is what I have so far, which only works once:

$(document.body).on('click','.button', function(){

    // Find highlight-current, then get the next instance and make that one current

    $('.highlight-current').parent().nextAll(".live-search-highlight").eq(0).removeClass('live-search-highlight').addClass('highlight-current');

    // Reset the previous one so it's no longer current

    $('.highlight-current:first').removeClass('highlight-current').addClass('live-search-highlight');

});

JsFiddle: http://jsfiddle.net/kthornbloom/g5skaek7/3/

Upvotes: 2

Views: 88

Answers (4)

charlietfl
charlietfl

Reputation: 171690

Simpler to just create a collection of all of the highlighted elements. Then use indexing to determine position of current/next.

Following will revert back to the start when the last one is reached

// create collection of all highlighted elements
var $highlights = $('.live-search-highlight'),
    // isolate the current one from collection and remove the secondary class
    $currHighlight = $highlights.filter('.highlight-current').removeClass('highlight-current'),
    // use index of current to determine next
    nextIndex = $highlights.index($currHighlight) + 1;
// revert to beginning if index is at the end
if(nextIndex === $highlights.length){
    nextIndex = 0;
}
// add secondary class to next (or first) in collection
$highlights.eq(nextIndex).addClass('highlight-current');

I would leave the main class and only add/remove the secondary class

DEMO

Upvotes: 3

deleted user
deleted user

Reputation: 832

The issue is that your code looks for the next .live-search-highlight via it's parent's siblings. This works the first time because the 1st highlight's parent is at the same level as the 2nd highlight. It doesn't work thereafter because it looks for highlights in the body's siblings.

body
    h1
        highlight1 -> parent = h1   (has highlight siblings)
    highlight2     -> parent = body (doesn't have any siblings)
    highlight3

You would have to store either:

  1. the highlights and iterate through the array rather than tree traversal, or
  2. the index of which highlight is currently highlighted

Upvotes: 1

JBux
JBux

Reputation: 1404

This should work.

var item_count = 0

$('.button').click(function(){
    $('.live-search-highlight').eq(item_count - 1).removeClass('highlight-current');
    $('.live-search-highlight').eq(item_count).addClass('highlight-current');
    item_count++

});

JSFiddle

Upvotes: 0

Ryan Neuffer
Ryan Neuffer

Reputation: 792

It helps if you don't remove 'live-search-highlight' class and instead increment an index you store. This allows you to loop back around in the document and would make implementing forward/back controls easy.

var currentIndex = 0,
totalMatches = 0,
currentClass = 'highlight-current',
normalClass = 'live-search-highlight';

$(document.body).on('click','.button', function(){

    var matches = $('.'+normalClass);

    totalMatches = matches.length;

    if(totalMatches === 0){
        return;
    }

    var newIndex = (currentIndex === totalMatches - 1) ? 0 : currentIndex + 1;

    matches.eq(currentIndex).removeClass(currentClass);
    matches.eq(newIndex).addClass(currentClass);

    currentIndex = newIndex;

});

Check the fiddle: http://jsfiddle.net/e00x5pbd/1/

Upvotes: 1

Related Questions