问题描述:

I have some kind of strange behaviour using jQuery's Click-Function. I also tried it with the on-EventHandler. There is some simple markup from Twitter's Bootstrap Navbar and I'm trying to change the CSS-Class of an li-tag. In this case I want to remove the CSS-Class active and add it to the currently clicked li-tag. But the change get's applied with a shift of one click. So when when e.g. 'Preview' is the current visual active element and I click on 'Document', the CSS-Class seems not to be changed. When I click afterwards on 'Slidecast', then the visual active element is 'Document' which is not the expected behavoiur. Next Click on 'Preview' and now 'Slidecast' is the visual active element. What I'm doing wrong? I tried it with remove and add and also with toggleClass, but that doesen't matter. Here is my code and markup. JS is wrapped into a Dom-Ready-Function.

<div class="navbar">

<div class="navbar-inner">

<ul class="nav">

<li class="active"><a href="#!document_defaultview">Document</a></li>

<li><a href="#!document_slidecast">Slidecast</a></li>

<li><a href="#!document_preview">Preview</a></li>

<li><a href="#!document_notes">Notes</a></li>

<li><a href="#!document_questions">Questions</a></li>

<li><a href="#!document_activities">Activities</a></li>

</ul>

</div>

</div>

JS

$("#document_navbar a").on('click', function(e) {

// Hide all content, display the one related to hash-tag

$(".document_view").toggle(false);

$(app_locationToId($(this).attr("href"))).toggle(true);

// Here is the part that does not work:

//$("#document_navbar li.active").removeClass("active");

//$("a[href='" + window.location.hash + "']").parent().addClass('active');

// Another try ... same result as described above!

$("#document_navbar li.active").toggleClass("active", false);

$("a[href='" + window.location.hash + "']").parent().toggleClass("active", true);

});

OK according to your answers, here is the code I've used to handle that problem:

$("#document_navbar a").on('click', function(e) {

new_location = app_locationToId($(this).attr("href"));

// Hide all content, display the one related to hash-tag

$(".document_view").toggle(false);

$(new_location).toggle(true);

// Change visual active li-tag

$("#document_navbar li.active").toggleClass("active", false);

$("a[href='" + app_IdToLocation(new_location) + "']").parent().toggleClass("active", true);

});

网友答案:

You can handle the hashchange event on the window object in order to add your 'active' class:

$(".navbar li a").on('click', function(e) {
    // Hide all content, display the one related to hash-tag    
    $(".document_view").toggle(false);    
    $('.navbar li').removeClass("active", false);
});

$(window).on('hashchange', function() {
    $("a[href='" + window.location.hash + "']").parent().addClass("active", true);
});

jsfiddle

网友答案:

When click function is triggered the window.location.hash is the one of the actual page. So you must be sure that the hash is changed and then take it and toggle class.

Searching for a code snippet on my stuff and edit/post it for you soon. :)

Edit:

So here you are, it's a snippet of one of my older projects before I started using history.js class:

$(function () {
    "use strict";
    var hashListener = null, hashValue = '', hashQuery;

    function checkIfHashChanged() {
        var hashQuery = window.location.hash;
        if (hashQuery === hashValue) { return; }
        hashValue = hashQuery;

        //Do the toggle
        $("#document_navbar li.active").toggleClass("active", false);
        $("a[href='" + hashQuery + "']").parent().toggleClass("active", true);
    }

    function startHashListener() {
        setInterval(checkIfHashChanged, 100);
    }

    function stopHashListener() {
        if (hashListener !== null) { clearInterval(hashListener); }
        hashListener = null;
    }

    startHashListener();

});

This code runs outside of your click function and just listens for a hashchange during interval hashlistener.

网友答案:

My best guess would be that window.location.hash gets updated after the click handler is done. As a result, you will always get the "old" location in your click handler. Afterwards the location gets updated, but you won't be using it until the next click... therefore you are always one click off.

To test this, I would put a short delay on the execution of the class toggle:

$("#document_navbar a").on('click', function(e) {

    // Hide all content, display the one related to hash-tag    
    $(".document_view").toggle(false);
    $(app_locationToId($(this).attr("href"))).toggle(true);

    setTimeout(function() {
        $("#document_navbar li.active").toggleClass("active", false);
        $("a[href='" + window.location.hash + "']").parent().toggleClass("active", true);
    }, 1000);
});
相关阅读:
Top