Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery loop through text occurrences

I need to be able to loop through the next occurrence of a given text on a page. Just like the most common 'find' function on almost every software (F3 - find next).

I'm trying to to that using jQuery but can't make it work by any means. Tried: NextAll(), next(), closest() (which seems bugged), find(), eq(), children(), etc., etc., etc.

Below is a sample that do work but it goes to the last element on the page and do not loop through.

function scrollMe(tow){
    var targetOffset = $("*:contains('"+tow+"'):last").offset().top;
    $('html,body').animate({scrollTop: targetOffset}, 1000);
}

To make it clear my page has a set of rows(divs) with text inside. Every time a user click on this row it must gently roll down (or up) to the next row with the occurrence of the text (if any).

Sample:

<div onclick="scrollMe('hello');">hello</div>
<div onclick="scrollMe('world');">world</div>
<div onclick="scrollMe('foo');">foo</div>
<div onclick="scrollMe('hello');">hello</div>
<div onclick="scrollMe('bar');">bar</div>

Indeed it should be enclosed by jQuery but it's just to illustrate.

like image 703
Paulo Bueno Avatar asked Feb 14 '12 15:02

Paulo Bueno


1 Answers

Here is a working example of scrolling to the next occurrence and highlighting it.

Since you're going to use a variable as the input to contains, I'd recommend skipping the selector. It's fast, but you're going to have trouble keeping the variable input sanitized.

This will, for example, highlight all the text occurrences of 'two' (fiddle example):

jQuery(function($) {
   var findText = 'two';
    $('*').filter(function() {
        return $(this).children().length < 1 && $(this).text().indexOf(findText) >= 0;
    }).addClass('hilite'); 
});

To make this work with some sort of find next functionality, you would need a variable to keep track of the current index, and some sort of trigger:

jQuery(function($) {
   // stores the currently highlighted occurence
   var index = 0;
   var findText = 'sed';

   // you could do this inside the click as well, here, it's cached/faster
   // inside click, it would be more dynamic and prevent memory leaks
   // just depends on your needs
   // you would also want to start with a parent element as $('*') is costly!
   var $occurrences = $('*').filter(function() {
       return $(this).children().length < 1 && $(this).text().indexOf(findText) >= 0;
    });

    // remove existing highlights, then find the next occurrence and highlight it
    $('#trigger').click(function() {
       if( index == $occurrences.length-1 ) { index = 0; }
       $occurrences.find('span.hilite').replaceWith(findText);
       var $next = $occurrences.eq(++index);
       $next.html( $next.html().replace(findText, '<span class="hilite">'+findText+'</span>') );
       $(document).scrollTop($next.offset().top-35);
       return false;
    });

    // scroll our trigger link when the screen moves so we can click it again
    $(window).scroll(function() {
        var top = $(window).scrollTop();
        $('#trigger').offset( {top: top, left: 0} );
    });

});
like image 197
Kato Avatar answered Oct 01 '22 00:10

Kato