Solved

Animated scroll to anchor on page from a js accordion menu

Posted on 2010-09-06
5
1,118 Views
Last Modified: 2012-05-10
I've got jquery accordion menu. When the buttons are clicked in that menu i want the page to scroll (animated) down to an anchor on the page.
I can get both of those to work individually but not together. It seems they are clashing in some way.
Here's the code:
<script>
$(function(){
    $('ul li a').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
        && location.hostname == this.hostname) {
            var $target = $(this.hash);
            $target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
            if ($target.length) {
                var targetOffset = $target.offset().top;
                $('html,body').animate({scrollTop: targetOffset}, 1000);
                return false;
            }
        }
    });
});
</script>

Open in new window

/* 
Simple JQuery menu.
HTML structure to use:

Notes: 

Each menu MUST have a class 'menu' set. If the menu doesn't have this, the JS won't make it dynamic
If you want a panel to be expanded at page load, give the containing LI element the classname 'expand'.
Use this to set the right state in your page (generation) code.

Optional extra classnames for the UL element that holds an accordion:

noaccordion : no accordion functionality
collapsible : menu works like an accordion but can be fully collapsed

<ul class="menu [optional class] [optional class]">
<li><a href="#">Sub menu heading</a>
<ul>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
...
...
</ul>
// This item is open at page load time
<li class="expand"><a href="#">Sub menu heading</a>
<ul>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
<li><a href="http://site.com/">Link</a></li>
...
...
</ul>
...
...
</ul>

Copyright 2007-2010 by Marco van Hylckama Vlieg

web: http://www.i-marco.nl/weblog/
email: marco@i-marco.nl

Free to use any way you like.
*/


jQuery.fn.initMenu = function() {  
    return this.each(function(){
        var theMenu = $(this).get(0);
        $('.acitem', this).hide();
        $('li.expand > .acitem', this).show();
        $('li.expand > .acitem', this).prev().addClass('active');
        $('li a', this).click(
            function(e) {
                e.stopImmediatePropagation();
                var theElement = $(this).next();
                var parent = this.parentNode.parentNode;
                if($(parent).hasClass('noaccordion')) {
                    if(theElement[0] === undefined) {
                        window.location.href = this.href;
                    }
                    $(theElement).slideToggle('normal', function() {
                        if ($(this).is(':visible')) {
                            $(this).prev().addClass('active');
                        }
                        else {
                            $(this).prev().removeClass('active');
                        }    
                    });
                    return false;
                }
                else {
                    if(theElement.hasClass('acitem') && theElement.is(':visible')) {
                        if($(parent).hasClass('collapsible')) {
                            $('.acitem:visible', parent).first().slideUp('normal', 
                            function() {
                                $(this).prev().removeClass('active');
                            }
                        );
                        return false;  
                    }
                    return false;
                }
                if(theElement.hasClass('acitem') && !theElement.is(':visible')) {         
                    $('.acitem:visible', parent).first().slideUp('normal', function() {
                        $(this).prev().removeClass('active');
                    });
                    theElement.slideDown('normal', function() {
                        $(this).prev().addClass('active');
                    });
                    return false;
                }
            }
        }
    );
});
};

$(document).ready(function() {$('.menu').initMenu();});

Open in new window

0
Comment
Question by:George-TCC
  • 3
  • 2
5 Comments
 
LVL 40

Expert Comment

by:gurvinder372
ID: 33609982
<<I can get both of those to work individually but not together>>
what does this mean? how did you tested individually? How should the script determine which anchor to scroll to when you click on an anchor in the menu list?


0
 

Author Comment

by:George-TCC
ID: 33613837
I can get the menu to work by itself and i can get the scrolling anchors to work by themselves but if i try to control the anchors with the menu it doesn't work.
In the menu in the li there will be an a tag to go to an id.
(This is not displayed in the current code)
eg. <li><a href="#anchor1">Anchor1</a>


0
 
LVL 40

Expert Comment

by:gurvinder372
ID: 33615889
Hmm...

In the approach you have mentioned in your last reply, you know the anchor tag you need to scroll down to by its id.
But if you do not have the id, or there is no mapping of the anchor tags (both above and below) available, how do you determine which anchor tag you should scroll down to.

If you want to map the anchor tags as per their order in both list, then
using this you can find the index of the item you have clicked
http://api.jquery.com/index/
using this you can access the item of the same index in another list
http://api.jquery.com/nth-child-selector/

0
 

Author Comment

by:George-TCC
ID: 33622686
The above code is just an example.
The nave would have to have something like <li><a href="#anchor1">Anchor1</a>
in it. Then somewhere down the page  in the html would have to be the anchor for the  button to link to.
The problem is that the button in the nav is inside an <li> If i make a button outside of the nav it scrolls down to the anchor properly.
Once the button is in the accordion nav and inside the <li> it no longer works.
0
 
LVL 40

Accepted Solution

by:
gurvinder372 earned 500 total points
ID: 33634095
If the link you are clicking has the information about which element you have to scroll down to (in the href attribute), then
you can simply use the following method

 $('ul li a').click(function()
 {
            var $target = $("#" + this.attr("href"));
            $target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
            if ($target.length) {
                var targetOffset = $target.offset().top;
                $('html,body').animate({scrollTop: targetOffset}, 1000);
                return false;
            }
});
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now