tags:

views:

286

answers:

5

I have a list of products. Each product has a title and a review link. Currently the titles link directly to the individual product page, and the review links go elsewhere.

I'd like to use a jquery each loop to cycle through each li, take the href from the title (the first link), and apply it to the review link (the second link), so they both point to the product page.

Simplified code would be as follows:

<ul>
   <li><a href="product1.html">Product 1</a><a href="review1.html">Review 1</a></li>
   <li><a href="product2.html">Product 2</a><a href="review2.html">Review 2</a></li>
   <li><a href="product3.html">Product 3</a><a href="review3.html">Review 3</a></li>
</ul>

I thought it would be something like the following:

$("li").each(function(){
   var link = $("a:eq(0)").attr('href');
   $("a:eq(1)").attr("href", link);
});

But it always uses the same variable "link".

Can someone help me out?

+3  A: 
$("li").each(function(){
   var link = $(this).find("a:eq(0)").attr('href');
   $(this).find("a:eq(1)").attr("href", link);
});
svinto
+8  A: 

I am passing this as an argument to define the context for each iteration of the each() loop. On each iteration, this refers to the element in question.

$("li").each(function(){
   var link = $("a:eq(0)", this).attr('href');
   $("a:eq(1)", this).attr("href", link);
});
gmcalab
+1 for use of context argument.
Gabriel
Maybe you should explain that the second parameter you pass to `$()` (namely `this` here) defines the context of the selector.
Felix Kling
A: 

Its because you are not using the li as the context of your a selection:

Try this:

$("li").each(function(){
    var a = $('a',this);
    var link = a.filter(":eq(0)").attr('href');
    a.filter(":eq(1)").attr("href", link);
});
PetersenDidIt
A: 

Try:

 $("li").each(function(){
    var link = $("a:eq(0)", this).attr('href');
 $("a:eq(1)", this).attr("href", link);
  });
David Neale
+1  A: 

Another option that avoids having to use .each entirely is to pass a function as the second argument to .attr.

This works as follows:

$('li').find('a:nth-child(2)').attr('href', function(index, href) {
    return $(this).prev('a').attr('href'); // use previous sibling's href
});

Essentially, it will take each element that matches the selector, pass it through the function, and then set the href attribute to the result of that function. The function will be passed arguments: the first is its index in the matching set ($('li a:nth-child(2)') here), and the second is the current value of the attribute. In your particular case, you don't care about either, but often you will want to transform an attribute based on its current value, so it can be handy.

Which one to use is entirely a matter of taste, jQuery sets allow you to do a lotof things without having to directly use .each.

Kent
Cool, cheers for this - nice to see a different take on the same problem. That's why I love jquery :-)
Sam