views:

88

answers:

3
+4  Q: 

jQuery selector

Hi how can i select and add a class to the prev and next a tag.

<div class="sub">
 <ul>  
   <li><a href="#">a</a>
    <ul>
     <li><a href="#">b</a>
      <ul>
     <li><a href="#">c</a></li>
     <li><a href="#">d</a></li>
     <li><a href="#">e</a></li>
    </ul>
    </li>
     <li><a href="#">f</a></li>
     <li><a href="#">g</a></li>
   </ul>
    </li>
   <li><a href="#">h</a></li>
   <li><a href="#">i</a></li>
   <li><a href="#">j</a></li>
   </ul>
</div>

example: now i want to add 2 css classes (.prev & .next) to the the according elements presume that the mouse is over the element <li><a href="#">g</a></li>, so i want to add the 2 classes to <li><a href="#">f</a></li> and <li><a href="#">h</a></li>

snip:

$(document).ready(function() {
    $('li').css({'border-top': '1px solid green','border-bottom': '1px solid green'});

    $('li a').each(
        function(intIndex){     
            $(this).mouseover(function(){
                $(this).css({'border-top': '1px solid red','border-bottom': '1px solid red'});
                    $(this).prev().find('li').css({'border-bottom': 'none'});
                    $(this).next().find('li').css({'border-top': 'none'});
                }).mouseout(function(){
                    $(this).css({'border-top': '1px solid green','border-bottom': '1px solid green'});
            });
        }    
    );
});

thanks in advance

+1  A: 

This should work. It loops through the entire .sub div though, so it may not be efficient if that list can get really long.

$(function() {
  $('.sub li>a').hover(
    function() {
      var curr = this;
      var last = '';
      var found = false;
      $('.sub li>a').each(function() {
        if(found)
        {
          $(this).addClass('next');
          return false;
        }
        if(this == curr)
        {
          found = true;
          $(last).addClass('prev');
          $(this).addClass('curr'); //you may want to do this too?
        }
        else
        {
          last = this;
        }
      });
    },
    function() {
      $('.sub li>a.next').removeClass('next');
      $('.sub li>a.prev').removeClass('prev');
    }
  );
});
Jenni
Thx for replies@all
john
+7  A: 

Try this: http://jsfiddle.net/rsEaF/1/

var $a = $('.sub li > a');

$a.mouseenter(function() {
    var index = $a.index(this);
    var prev = (index - 1 >= 0) ? $a.eq(index - 1).addClass('prev') : $();
    var next = $a.eq(index + 1).addClass('next');
    $a.not(prev).not(next).removeClass('prev next');
});​

EDIT: One minor correction. Previously, if you hovered over the first item, the .prev class would be added to the last item in the list. This has been corrected.


EDIT: Here's a version that uses .each() to assign the handler. Doing it this way is a little more efficient because it removes the need to call $a.index(this); for each mouseenter.

Try it out: http://jsfiddle.net/rsEaF/3/

var $a = $('.sub li > a');

$a.each(function(index) {
    $(this).mouseenter(function() {
        var prev = (index - 1 >= 0) ? $a.eq(index - 1).addClass('prev') : $();
        var next = $a.eq(index + 1).addClass('next');
        $a.not(prev).not(next).removeClass('prev next');
    });
});​

EDIT: If you're having any issue with the proper class being removed consistently, get rid of this line of code:

$a.not(prev).not(next).removeClass('prev next');

and at the beginning of the handler, replace it with:

$a.removeClass('prev next');

or:

$a.filter('.prev,.next').removeClass('prev next');
patrick dw
+3  A: 

You should make an effort to avoid attaching event listeners like this

$('li a').each(function (el) {
    $(el).mouseover(function (e) {
        /* event handler code */
    });
});

It is sufficient (and more efficient) to attach a listener like so:

$('li a').mouseover(function (e) {
    /* event handler code */
});

Also jQuery 1.3 introduces .live() (see http://api.jquery.com/live/)

$('li a').live('mouseover', function (e) {
    /* event handler code */
});

Any event thrown by an element that matches the selector, whether it exists when .live() is called or is created later, will be passed to the specified function.

Ryan Tenney
-1 "you should never attach event listeners like this". Bad advice. When you don't add any elements, using `.live()` is not necessary and introduces additional complexity (thus a slower execution). `.live()` **is** a very useful function, but you shouldn't *always* use it.
MvanGeest
Ryan - With all due respect, that is not necessarily true. Here's a version of my answer that uses `.each()` to assign the handler, which provides a unique benefit. It utilizes the `index` property of `.each()` which obviates the need to find the `.index()` of the hovered element on the fly. See it here: http://jsfiddle.net/rsEaF/3/
patrick dw
@Ryan W Tenney: I see what you mean now, and you're mostly right: you can leave out `.each()` and just attach to all the elements at the same time. But patrick dw found a valid use for attaching using `.each()`. I took back the -1 after you edited your answer.
MvanGeest
Patrick - I like your solution to the problem, and I would agree that in this case using `.each()` enormously simplifies the solution. Well done.@MvanGeest - I updated my answer to reflect that `.live()` isn't the only option, and softened my criticism of the approach taken by the question author.
Ryan Tenney