jquery: hashchange, prevent jumping to hash

user1374796 picture user1374796 · Apr 11, 2013 · Viewed 21.8k times · Source

I have a hashchange function set up to show/hide different sections of an about page without having 7 separate pages. This all works fine, great infact, there's just one small thing that's bothering me, when the relevant content is shown on screen, eg: #about01 if you click on the menu button again the browser jumps down to the top of this div, which I don't want to happen.
Here's my jQuery:

jQuery(document).ready(function(){

    jQuery(window).on('hashchange', function(){
        var hashFound = determineContent();
        if(hashFound) return false;
    });

    function determineContent(){

        var hash = window.location.hash;
        jQuery('.about').hide();

        jQuery('.sub-menu').each(function(){

             if (jQuery(this).attr('hook') === hash.replace('#about', '')) {
               jQuery('#about'+jQuery(this).attr('hook')).fadeIn();
                 return true;
             }
        });

        jQuery('html, body').animate({scrollTop:0}, 'slow');
        return false;
    }

    determineContent();
});

HTML:

<div id="sub-menu">
        <li id="sub-menu-01" class="sub-menu" hook="01"><a href="#about01">TEST</a></li>
        <li id="sub-menu-02" class="sub-menu" hook="02"><a href="#about02">TEST</a></li>
        <li id="sub-menu-03" class="sub-menu" hook="03"><a href="#about03">TEST</a></li>
        <li id="sub-menu-04" class="sub-menu" hook="04"><a href="#about04">TEST</a></li>
        <li id="sub-menu-05" class="sub-menu" hook="05"><a href="#about05">TEST</a></li>
        <li id="sub-menu-06" class="sub-menu" hook="06"><a href="#about06">TEST</a></li>
        <li id="sub-menu-07" class="sub-menu" hook="07"><a href="#about07">TEST</a></li>
    </div>

<div id="about01" class="about">CONTENT HERE
</div>

<div id="about02" class="about">CONTENT HERE
</div>

<div id="about03" class="about">CONTENT HERE
</div>

<div id="about04" class="about">CONTENT HERE
</div>

<div id="about05" class="about">CONTENT HERE
</div>

<div id="about06" class="about">CONTENT HERE
</div>

<div id="about07" class="about">CONTENT HERE
</div>

Like I say, if #about01 is shown, and the user then clicks on #sub-menu-01 again, the window scrolls down to the top of this div, as is the normal behaviour for hashes in url's. Is the a way to prevent the default behaviour and not scroll to the top of this div on the click?
Also, I'm trying to figure out if there's a way to show #about01 on the page load of www.website.com/about instead of having to put in www.website.com/about/#about01 etc?

Answer

gp. picture gp. · Apr 11, 2013

problem is in your jquery.each block.

"return true" inside jquery.each block will not return but continue for next items. Also, this will not return from your determineContent function, so the next code for scroll will also be executed and determineContent will always return false.

use a flag e.g.

var found = false;
JQuery.each(function(){
   if(found) return;
   //if your condition is true then found = true
})

if(found) return true;
//else continue the next line.