?
Solved

Animated scroll to anchor on page from a js accordion menu

Posted on 2010-09-06
5
Medium Priority
?
1,133 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 40

Expert Comment

by:Gurvinder Pal Singh
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:Gurvinder Pal Singh
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:
Gurvinder Pal Singh earned 2000 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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
In this tutorial viewers will learn how to embed an audio file in a webpage using HTML5. Ensure your DOCTYPE declaration is set to HTML5: : The declaration should display (CODE) HTML5 is supported by the most recent versions of all major browsers…
In this tutorial viewers will learn how to style rounded corners for elements in CSS using the border-radius property Begin with a normal styled element such as a div: To style all four corners of the div to be the same degree of roundness, use the …
Suggested Courses

764 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