views:

82

answers:

2

i have this jquery code that retrieves external content using ajax, without refereshing the page, and i also have a navigation links that has the different background color when user is on the current page.

the jquery code:

function loadPage(url)  //the function that loads pages via AJAX
{
    url=url.replace('#page','');    //strip the #page part of the hash and leave only the page number

    //$('#loading').css('visibility','visible');    //show the rotating gif animation
        $('.counter').html('<img src="img/ajax_load.gif" width="16" height="16" style="padding:12px" alt="loading" />');

    $.ajax({    //create an ajax request to load_page.php
        type: "POST",
        url: "load_page.php",
        data: 'page='+url,  //with the page number as a parameter
        dataType: "",   //expect html to be returned
        success: function(msg){

            if(parseInt(msg)!=0)    //if no errors
            {
                $('#change-container').html(msg);   //load the returned html into pageContet


            }
        }

    });

}

the html navigation code:

<ul>
   <li class="current"><a href="#page1">Home</a></li>
   <li><a href="#page3">Replies</a></li>
   <li><a href="#page4">Favorites</a></li>
   </ul>

so basically when someone clicks on the replies link, i want the li class to change to current, to indicate that your at that page. sorry for the newbie question :))

+1  A: 

This will work for what you want, with limitations:

$('ul a').click(
    function(){
        $('.current').removeClass('current');
        $(this).addClass('current');

        return false;
    }
);

The problems are:

  1. No id for the parent ul, so this (presumably navigation) ul is no different from any other on the page,
  2. This means that if any link (a) within any ul is clicked that link will get the current class-name. This may be what you want, but I wouldn't recommend it, it's too easy to end up with unwanted behaviour.

Suggestion:

Give the parent ul an id (that way it's identified uniquely on the page), for example 'navigation', this allows the jQuery to become highly selective.

$('#navigation a').click(
  function() {
    $('.current','#navigation').removeClass('current');
    $(this).addClass('current');
    return false;
  }
);

This also partially addresses the concerns raised by @Alec in the comments, as the id provides a unique context in which to search for the .current element, preventing effects from being scattered around the page.

David Thomas
Targeting `$('.current')` means that every element (also outside this menu) with the class 'current' will have its class removed. It's better to target e.g. `$(this).closest('ul').find('li.current')`. And `$(this)` refers to the `a` element, not the `li`, so that should be `$(this).parent()`.
Alec
@Alec, agreed. I never mentioned that in the first instance, because I felt it was my fault for not coming up with something as scarily-efficient looking as @patrick (I'm simple folk, still, sadly). But it *is* one of the benefits I mention following the **suggestion**.
David Thomas
David - You should remove the `>` from your first solution, because it is a [`child-selector`](http://api.jquery.com/child-selector/) and there are no `<a>` elements that are a direct child of `<ul>`. :o)
patrick dw
@patrick, yeah, I...gosh. I originally used `$('ul > li > a')` as the selector, and edited it to remove the `li`...apparently leaving one of the `>`s behind. Oops. Thanks =)
David Thomas
+2  A: 

Example: http://jsfiddle.net/4cs9h/

$('ul > li > a').click(function() {
    var $th = $(this).parent();
    if( !$th.hasClass('current') ) {
        $th.addClass('current')
               .siblings('.current').removeClass('current');
        loadPage(this.href);
    }
    return false;
});

The $th variable refers to the parent <li> of the <a> that was clicked.

If the <li> does not have the current class, the class will be added and will be removed from any siblings that have that class, and loadPage() will be called, sending the href attribute of the clicked <a>.


With regard to your comment, yes it would be a good idea to target the specific <ul> with an ID.

$('#navigation > li > a').click(function() {...

HTML

<ul id="navigation">
   <li class="current"><a href="#page1">Home</a></li>
   <li><a href="#page3">Replies</a></li>
   ...

To use a hash value included in the page, you can pass it to the loadPage() function.

var hash = window.location.hash;

    if( !hash || hash === '#' )
        hash = "#page1";

loadPage( hash );
patrick dw
thanks for the great answer would it better to give the ul a class or an id!! and how can put that on the jquery code you provides, so it only targets the ul list that i want i.e. #navigation
getaway
@getaway - I'd definitely place an ID on the `<ul>` so you target that specific one. I'll update my answer.
patrick dw
thanks, can i just ask where shall i put that on my jquery code above, so basically when it loads then you can current the link
getaway
p.s it works with the home link, but not the replies link
getaway
@getaway - Do you mean when the page loads with a `hash` in the URL? You could pass the hash, or a default value to `loadPage()`. I'll update.
patrick dw
@getaway - I see there may be another issue. In the `click` handler, instead of `loadPage(this.href);`, try `loadPage(this.hash);`.
patrick dw
oh my god how did you know that was already on my page!!! the whole jquery code is here http://jsfiddle.net/bKbh3/ can you please check it out, and see whats the problem +up vote for you :))
getaway
@getaway - You need to remove the click handler out of the `success:` callback, and add it at the top in place of the other click handler. I also changed it to use `this.hash`. Here's an update: http://jsfiddle.net/bKbh3/3/
patrick dw
@patrick thanks, but its still not working!!! the page loads fine, but the current attribute is not moving to replies, it stays at the home link
getaway
@patrick it works thanks
getaway