Question

I have some javascript/jQuery that attaches a class 'active' to my .section that is currently displaying (and then scrolls to the active class).

What I'm trying to achieve is to simply set a class on my navigation menu spans based on what section is active (so the current 'page' is displayed).

What would be the best way to achieve this? My nav is nested outside my sections, and I want to end up with something akin to

if($('#page1').hasClass('active'){
   $('.label1').addClass('show') .siblings().removeClass('show');
}

What is the best practice for this type of nav. display?

edit: Current test version of the site is here: http://thetearoom.server105.com/indexv6.html

I know these are long and a bit messy so bear with me please =)

html:

<body>
    <div class="static">

    <div id="top">

    <!--            THIS IS FOR LATER HEADER-->
    <div id="headerlogo">

    </div>
    <div id="headertext">  </div>     
    </div>
        </div>
        <ul class="vnav">
            <li><a href="#p1" onclick="$('#p1').addClass('active') .siblings().removeClass('active');">
                    <span class="label2">WELCOME</span>
            </a></li>
            <li><a href="#p2" onclick="$('#p2').addClass('active') .siblings().removeClass('active');">
                    <span class="label3">ABOUT US</span>
            </a></li>
            <li><a href="#p3" onclick="$('#p3').addClass('active') .siblings().removeClass('active');">
                    <span class="label4">AFTERNOON TEA</span>
            </a></li>
        </ul>

    <!--        FOR NOW P1 CONTAINS HEADER AND P3 CONTAINS FOOTER-->
    <div id="container">
<!--                        THESE WERE THE ENTIRE IMAGE VERSIONS OF THE OVERLAYED FLOATS-->
<!--                <div id="blur" data-0="background-position:0em 18em;" data-3000="background-position:0em -4em;"></div>
            <div id="focus" data-0="background-position:0em 0em;" data-3000="background-position:0em 10em;"></div>-->


        <div id="p1" class="section">
            <div class="content">
<!--                    floatcontent-->

                    <img src="img/focus/lhs_toppetal.png" alt="" height="75" width="165" class="overlay" id="lhs_toppetal" data-0="top:20%;" data-end="top:80%;">
                    <img src="img/focus/rhs_petal.png" alt="" height="205" width="261" class="overlay" id="rhs_petal" data-0=" bottom:-8%;" data-end="bottom:-82%;">
                    <img src="img/blur/top_petalright.png" alt="" height="56" width="125" class="overlay" id="top_petalright" data-0="bottom:36%;" data-end="bottom:95%;">
                    <img src="img/blur/top_petalleft.png" alt="" height="98" width="125" class="overlay" id="top_petalleft" data-0="top: 77%;" data-end="top:10%;">
                    <div id="title">


                    </div>
                <div class="tbb" id="tb1">
                <div class="textbox" id="welcome">
                    <h3>Welcome</h3>
                    <p>
                        Creating experiences beyond comparison...<br>
                        The Tea Room offers traditional afternoon tea, a la carte lunch,<br>
                        private events and wedding receptions. Renowned for beautiful venues
                        in historic locations, this is a world class dining experience.
                    </p>
                </div>
                </div>  
<!--                        THIS IS THE SCROLL BUTTON-->
                    <div class="next" data-0="z-index:120;" data-650="z-index:120;" data-680="z-index:-1;"><a href="#p2" onclick="$('#p2').addClass('active') .siblings().removeClass('active');"><span></span></a></div>
        </div>
        </div>

<!--            <div class="divider">Simple Divider</div>-->

        <div id="p2" class="section">

            <div class="content">
<!--                    floatcontent-->
                    <img src="img/focus/lhs_petal.png" alt="" height="205" width="261" class="overlay" id="lhs_petal" data-500="top:66%;" data-end="top:10%;">
                    <img src="img/blur/middlerightpetal.png" alt="" height="217" width="333" class="overlay" id="middlerightpetal" data-500="top: 31%;" data-end="top:5%;">
                    <img src="img/blur/middleleftpetal.png" alt="" height="163" width="368" class="overlay" id="middleleftpetal" data-100="top: -13%;" data-end="top:28%;">

                <div class="tbb">
                <div class="textbox" id="about">
                    <h3>About Us</h3>
                    <p>
                        Sed dictum quam a urna feugiat ornare. Donec vel viverra ligula. Duis 
                        eu placerat magna. Phasellus facilisis vestibulum consectetur. Suspendisse
                        vestibulum ligula orci, non feugiat ligula rhoncus non. Duis sit amet bibendum 
                        nibh. Nulla eros risus, sagittis ut lectus quis, lacinia pharetra augue. Vestibulum 
                        diam velit, consequat vel ornare at, scelerisque non nisi.<br>
                        Curabitur elementum gravida odio nec volutpat. Phasellus vel ligula eu mauris dapibus
                        onsequat non nec quam. Sed quis justo sit amet tortor varius auctor in porta orci. Quisque
                        posuere tortor, at facilisis libero. Nam nec placerat tortor, commodo cursus neque.
                        Aliquam erat volutpat. Aliquam erat volutpat. Etiam aliquet mollis consectetur.
                    </p>
                </div>
                </div>
                    <div class="next" data-680="z-index:110;" data-1300="z-index:110;" data-1350="z-index:-1;"><a href="#p3" onclick="$('#p3').addClass('active') .siblings().removeClass('active');"><span></span></a></div>
            </div>
        </div>

<!--             <div class="divider">Simple Divider</div>-->

        <div id="p3" class="section">
            <div class="content">
<!--                    FLOAT IMAGES  focus-->
                <img src="img/focus/macaroon.png" alt="" height="180" width="180" class="overlay" id="macaroon" data-1000="top: 90%;" data-end="top:18%;">
                <img src="img/focus/large_lower_cake.png" alt="" height="180" width="180" class="overlay" id="large_lower_cake" data-1000="bottom: 58%;" data-end="bottom: 28%;">
                <img src="img/focus/scroll_lower.png" alt="" height="45" width="55" class="overlay" id="scroll_lower" data-1000="bottom: 62%;" data-end="bottom: 17%;">
<!--                    FLOAT IMAGES    blur-->
                <img src="img/blur/lhs_halfscroll.png" alt="" height="356" width="210" class="overlay" id="lhs_halfscroll" data-1000="top: 95%;" data-end="top: 45%;">
                <img src="img/blur/lrhs_creamcake.png" alt="" height="115" width="118" class="overlay" id="lrhs_creamcake" data-1000="bottom: 7%;" data-end="bottom: 23%;">
                <img src="img/blur/llhs_cake.png" alt="" height="115" width="118" class="overlay" id="llhs_cake" data-1000="bottom: 78%;" data-end="bottom: 18%;">
                <div class="tbb">
                <div class="textbox" id="aftertea">
                    <h3>Afternoon Tea</h3>
                    <p>
                         Sed dictum quam a urna feugiat ornare. Donec vel viverra ligula. Duis 
                        eu placerat magna. Phasellus facilisis vestibulum consectetur. Suspendisse
                        vestibulum ligula orci, non feugiat ligula rhoncus non. Duis sit amet bibendum 
                        nibh. Nulla eros risus, sagittis ut lectus quis, lacinia pharetra augue. Vestibulum 
                        diam velit, consequat vel ornare at, scelerisque non nisi.<br>
                        Curabitur elementum gravida odio nec volutpat. Phasellus vel ligula eu mauris dapibus
                        onsequat non nec quam. Sed quis justo sit amet tortor varius auctor in porta orci. Quisque
                        posuere tortor, at facilisis libero. Nam nec placerat tortor, commodo cursus neque.
                        Aliquam erat volutpat. Aliquam erat volutpat. Etiam aliquet mollis consectetur.
                    </p>
                </div>
                </div>
<!--                    <div class="reset" ><a href="#p1"><span></span></a></div>-->
                    <div class="next" data-0="z-index:105;"><a href="#p1" onclick="$('#p1').addClass('active') .siblings().removeClass('active');"><span></span></a></div>
            </div>
        </div>



    </div>

    <footer>
    <!--            THIS IS FOR LATER FOOTER-->

        <div id="footer">

            <ul class="footlist">
                <li><a href="#">FACEBOOK</a></li>
                <li><a href="#">TWITTER</a></li>
                <li><em>&copy;</em>&nbsp;COPYRIGHT <strong>2012</strong> GRAND PACIFIC GROUP&nbsp;&nbsp;&nbsp;<em>|</em><a href="#">CAREER ENQUIRIES</a></li>
            </ul>
         </div>   

    </footer>

</body>

js:

<!--    THIS GIVES US A SMOOTH MOUSEWHEEL SCROLL-->
<!--        <script type="text/javascript" src="js/jquery-1.9.1.js"></script>-->


<!--        THIS HANDLES THE PARALLAX ANIMATIONS-->
    <script type="text/javascript" src="js/skrollr.min.js"></script>
    <script type="text/javascript" src="js/skrollr.menu.min.js"></script>
    <script type="text/javascript">
     /*Code below based on section from jsfiddle.net/NGj7E, Author unknown*/
     /*This code now selects .section class and applies active to it, scrolling to active
      * class and removing active class attr. when page scrolls. 
      * 
      * Page-by-Page works in both vertical directions and stops the default
      * wheel event from happening. Parallax will not work without js enabled.*/

         /*Set class to active on first element this serves as our indicator
          *     -.section is class to have active applied to*/
         $('.section').first().addClass('active');
         /*This handles the mousewheel event*/
             $(document).on('mousewheel DOMMouseScroll', function (e) {

        e.preventDefault();//prevent the default mousewheel scrolling
        var active = $('.section.active');
        //get the delta to determine the mousewheel scrol UP and DOWN
        var delta = e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1;

        //if the delta value is negative, the user is scrolling down
        if (delta < 0) {
            //mousewheel down handler
            next = active.next();
            //check if the next section exist and animate the anchoring
            if (next.length) {
               /*setTimeout is here to prevent the scrolling animation

                to jump to the topmost or bottom when 
                the user scrolled very fast.*/
                var timer = setTimeout(function () {
                    /* animate the scrollTop by passing 
                    the elements offset top value */
                    $('body, html').animate({
                        scrollTop: next.offset().top
                    }, 1200, 'swing');

                    // move the indicator 'active' class
                    next.addClass('active')
                        .siblings().removeClass('active');


                    clearTimeout(timer);
                }, 420);
            }

        } else {
            //mousewheel up handler
            /*similar logic to the mousewheel down handler 
            except that we are animate the anchoring 
            to the previous sibling element*/
            prev = active.prev();

            if (prev.length) {
                var timer = setTimeout(function () {
                    $('body, html').animate({
                        scrollTop: prev.offset().top
                    }, 1200, 'swing');

                    prev.addClass('active')
                        .siblings().removeClass('active');

                    clearTimeout(timer);
                }, 420);
            }

        }

        if($('#page1').hasClass('active'){

        })
    });





    var s = skrollr.init({
    forceHeight: false,
            smoothScrolling: true,
            smoothScrollingDuration: 50

    });

    skrollr.menu.init(s, {
             easing: 'swing',
             animate: true,
             duration: function(currentTop, targetTop){
                 return Math.abs(currentTop - targetTop) * 1.4;
             }

            });

    </script>
Was it helpful?

Solution

Okay so ... in order for this to work in an extensible way, you will need to separate those inline onclick functions to an external handler. Which you should be doing anyway, especially if using jQuery cuz its so easy. I won't go into the details on that too much, but regardless, update your script as such:

$(function(){
    // scroll stuff

    $('.vnav').on('click','a',function(){
        var self = this,
            eqNum = (parseInt(self.href.slice(-1),10) - 1);

        $('.active')
            .removeClass('active')
            .parent()
            .find('.section')
            .eq(eqNum)
            .addClass('active');

        $('.show').removeClass('show');

        $(self).find('span').addClass('show');
    });
});

This capitalizes on delegation so there is only one click handler, but also reduces the amount of DOM traversal. It captures the "counter value" in the href of the link which corresponds to the id of the section to activate. Then it removes the active class for the currently active item, searches for the new active based on the link clicked, and adds the active class to it. Finally, it removes the active show span, and adds it to the span inside the link clicked.

Not tested, but should work.

EDIT

Lets get the scroll involved! Might as well build out the entire function now:

$(function(){
    var $navLinks = $('.vnav').find('a');

    $('.section').first().addClass('active');

    $(window).on('scroll',function(e){
        e.preventDefault();

        var $active = $('.active'),
            $show = $('.show'),
            delta = (e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1);

        if (delta < 0) {
            var $next = $active.next(),
                $nextLink = $next.get(0).id;

            if(next.length){
                var timer = setTimeout(function(){
                        $('body, html').animate({
                            scrollTop:$next.offset().top
                        },1200,'swing');

                    $active.removeClass('active');
                    $next.addClass('active');

                    $show.removeClass('show');
                    $navLinks.filter(function(){
                        return this.href === '#'+$nextLink
                    }).find('span').addClass('show');

                    clearTimeout(timer);
                },420);
            }
        } else {
            var $prev = $active.prev(),
                $prevLink = $prev.get(0).id;

            if(prev.length){
                var timer = setTimeout(function () {
                    $('body, html').animate({
                        scrollTop:$prev.offset().top
                    },1200,'swing');

                    $active.removeClass('active');
                    $prev.addClass('active');

                    $show.removeClass('show');
                    $navLinks.filter(function(){
                        return this.href === '#'+$prevLink
                    }).find('span').addClass('show');

                    clearTimeout(timer);
                }, 420);
            }

        }
    });

    $('.vnav').on('click','a',function(){
        var self = this,
            eqNum = (parseInt(self.href.slice(-1),10) - 1);

        $('.active')
            .removeClass('active')
            .parent()
            .find('.section')
            .eq(eqNum)
            .addClass('active');

        $('.show').removeClass('show');

        $(self).find('span').addClass('show');
    });
});

Again untested, but hopefully should be okay. I cached .vnav's a elements, which is combined on the scroll process with a filtering of the elements to match the ID that corresponds to the appropriate link. Once this link is found, we can apply the span. I also did a couple of optimizations, and bound the scroll event to the window (which is the appropriate way to handle scroll events in jQuery).

Even if this doesn't remedy everything, it should give you a decent starting point. I hope haha.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top