views:

42

answers:

2

I'm a noob in jQuery and have stuck at this. I have the following HTML code output from a PHP page:

<ul class="cats">
  <li><span><a href="cant_post_link_yet1">Lifestyle</a></span></li>
  <li><span><a href="cant_post_link_yet2">Entertainment</a></span></li>
  <li class="has_child">
    <span><a href="cant_post_link_yet3">Technology</a></span>
    <ul class="subcats">
      <li><span><a href="cant_post_link_yet4">Gadgets</a></span></li>
      <li><span><a href="cant_post_link_yet5">Hardware</a></span></li>
    </ul>
  </li>
  <li><span><a href="cant_post_link_yetsports">Sports</a></span></li>
  <li class="has_child">
    <span><a href="cant_post_link_yet6">Design</a></span>
    <ul class="subcats">
      <li class="has_child">
        <span><a href="cant_post_link_yet7">Web Design</a></span>
        <ul class="subcat">
          <li><span><a href="cant_post_link_yet8">Adobe Photoshop</a></span></li>
        </ul>
      </li>
      <li><span><a href="cant_post_link_yet9">Graphics and Print</a></span></li>
    </ul>
  </li>
</ul>

What's the correct jQuery code so that I can modify the href attribute for the first-level list only? Basically, I want to change the href of Technology and Design to be "#" but will not change the href of Web Design which is already on second-level list.

More Info: In the code above, if list has subcategories, then it has the class has_child, whether it's on first-level or not. So I want only the first-level list which has class has_child to be modified the href to "#" I can't alter output anymore because it's in the PHP code.

Any help is greatly appreciated.

A: 

There are a few ways of doing it. The most straightforward is to trace the child elements directly:

$("ul.cats > li > span > a").attr("href", "....");

Of course that has issues if the anchors aren't contained in spans. You can instead take an exclusionary approach:

$("ul.cats > li > :not(ul) a").attr("href", "...");

This will be slower but might be closer to the intended semantics. It does suffer from a similar issue to the first in that the child lists might not be directly below the list element.

cletus
Thanks for the quick response, it's what I am looking for - the first code.I have almost similar approach earlier: $("ul.cats > li span a").attr("href", "...."); and it did not work. Can you point me out what's the wrong with it?
bloggerious
See my answer and check whether it works. Also the HTML you have posted is not well formed.
rahul
@rahulYes this one and yours is working perfectly but I'm using your answer since it's specific to .has_child. The HTMl I posted has missing </ul> since it's not the complete output.
bloggerious
@bloggerious yours doesn't work because `>` is a child selector and without that it's a descendant selector so `ul.cat > li span a` will find the direct children of `ul.cats` but then find all `span a` descendants, which includes the links in the child lists. That's why mine has `>` all the way down.
cletus
@cletusThanks for the explanation. At least I learn a little day by day :)
bloggerious
+1  A: 
$("ul.cats > li.has_child > span > a").attr("href","#");

ul.cats > li.has_child selects all first level li elements with class name has_child inside the ul with class name cats. > span > a then selects all a elements which are first level elements inside span which is direct child of the previous selector.

rahul