JQuery sliding menu - Remember which link was clicked

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
JQuery sliding menu - Remember which root a link that was clicked was in

Hello,

I am working on a jQuery sliding menu on my site. It is working just fine, although, when someone clicks on a link to go to a new page regardless of which page they go to it always expands the first root div (which is what I told it to do if it is the first time a page is being loaded). What I want it to do is for people to click on a link and when the page reloads and that root would still be expanded. I would guess that you would create a variable that stored the data of which one and it would use that, but I don't know how to get which.

Here is a link to a live site.

Here is my javascript:
Code:
$(document).ready(function() {
    $(".menu .menuItemHeader").next().hide(); // Hide all when page loads
    $(".menu .menuItemHeader:first").next().slideDown('fast'); // Show the first when page loads
    $(".menu div").click(expandMenuItem); // Expand item that was clicked
    $(".menuExpand div").click(changePage); // Move to page depending on item clicked
});
 
function changePage() {
    var URL = $(this).children().attr("href");
    window.location = URL;
    return false;
}
 
function expandMenuItem() {
    if($(this).next().is(":hidden")) {
         $(".menu .menuItemHeader").next().slideUp('normal');
         $(this).next().slideDown('normal');
    }
}

If you need it here is the HTML
HTML:
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="collapseMenu.js"></script>
<link rel="stylesheet" type="text/css" href="../CSS/menu.css" />
<div class="menu">
    <div class="menuHeader">
         <h3>Navigation</h3>
    </div>
    <div class="menuItems">
         <div class="menuItemHeader">Root 1</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
          </div>
         <div class="menuItemHeader">Root 2</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
              <div class="menuExpand"><a href="#">Child 2</a></div>
              <div class="menuExpand"><a href="#">Child 3</a></div>
          </div>
          <div class="menuItemHeader">Root 3</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
              <div class="menuExpand"><a href="#">Child 2</a></div>
          </div>
      </div>
      <div class="menuFooter">&nbsp;</div>
</div>

Note: For some reason my stylesheet doesn't always work with this little demo I made, so if it comes out as just text refresh the page.
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
You'll need some way of differentiating the links via the URL. Since the anchors link to the same page, use a fragment identifier (add a different one to each link). Have your ready hander check the fragment (window.location.hash) to determine which menu to expand.
 

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
Well, in the example I used a hash because I didn't want to write out every link, this is still the beta version of a site I'm working out. So, how would I get which I need?
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
If the links go to the same page (as they do in the posted & linked samples), use different fragments to differentiate the menus.
HTML:
<ul class="menu">
  <li>Menu 1
    <ul>
        <li><a href="#menu1_item1">Child 1</li>
        <li><a href="#menu1_item2">Child 2</li>
        ...
    </ul>
  </li>
  <li>Menu 2
    <ul>
        <li><a href="#menu2_item1">Child 1</li>
        <li><a href="#menu2_item2">Child 2</li>
        ...
    </ul>
  </li>
  ...
</ul>

If the links go to different pages, you can use the path to differentiate the menus. Examine the path of the current page (window.location.pathname) to determine which menu to open.

In either case, write a function or class that takes a URL and returns a path of menus to the child linking to the URL. It could determine this by examining the menu or by using a canned data structure that maps URL pieces to menu paths. If you're using fragments, you could also format them to hold the path to the menu item (as done in the example).
 
Last edited:

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
So it would be something like:
Code:
// ...
var whichMenu = window.location.pathname;
$(".menu .menuItemHeader:"+whichMenu).next().slideDow();
// ...
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
That selector won't work, but you should be able to use a [href=...] attribute selector to find the child, then expand its ancestors up to the top menu.
 
Last edited:

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
Ok, so tell me if I'm doing this right.

It would be:
Code:
// ...
var whichLink = window.location.pathname;
$(".menuExpand a[href='"+whichLink+"']").parent().parent().slideDown('fast');

I close the menuHeader div so it isn't a child of that, what can I use to get the menuHeader?
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
That looks right. However, links will need to be absolute paths. If you don't want that and the final path element is unique among the menu links, you can extract the final path element and use the attribute-ends-with selector ([href$=...]). For example,
Code:
// if links never include a trailing "/", capture only the non-/ characters
var whichLink = (/[^/]+\/?$/.exec(window.location.pathname))[0];
$('.menu a[href$=' . escape(whichLink) . ']').parents('ul').slideDown('fast');

You can use $.parents() to get the ancestors of an element, filtered by a given selector.
 

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
The way I am doing it involves several div tags. in this order:
HTML:
    <div class="menuItems">
         <div class="menuItemHeader">Root 1</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
          </div>
         <div class="menuItemHeader">Root 2</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
              <div class="menuExpand"><a href="#">Child 2</a></div>
              <div class="menuExpand"><a href="#">Child 3</a></div>
          </div>
          <div class="menuItemHeader">Root 3</div>
          <div class="menuSection">
              <div class="menuExpand"><a href="#">Child 1</a></div>
              <div class="menuExpand"><a href="#">Child 2</a></div>
          </div>
      </div>
      <div class="menuFooter">&nbsp;</div>
</div>
Can I still get to <div class="menuItemHeader"> even when I close that right after the text

Example:

<div class="menuItemHeader">Root1</div>
<div>
<div><a></a>
</div>
</div>


Is there any way to get that because I don't think it works like this:
Code:
$('.menu a[href$=' . escape(whichLink) . ']').$(".menuItemHeader").next().slideDown('fast');
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
You can get the preceding .menuItemHeader using $.prev() on the link's ancestor.

Code:
$('.menu a[href$=' . escape(whichLink) . ']').parent(".menuSection").prev()

However, that looks to be of little use, since you want .menuSection.

Note that by switching from <div>s to the more semantic <ul> and <li>, you can decrease the size of the source code.
 

as4s1n

New Member
Messages
174
Reaction score
4
Points
0
Ok, I just realized I have a problem. My website uses an include in the main page, so whenever it calls the window.location.pathname variable it always returns index.php. Is there any way to fix that? Or would it be better to just use the variable in the URL?
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Use whichever portion of the URL identifies the link. However, even if you have a single entry point to your site, this shouldn't be reflected in the public URI. Use rewrites to present a readable external URI so your single entry point only appears in internal URIs. Since JS is client side, it will only see the public URI so the single entry point won't matter. Additionally, you don't need to include "index.php" in public URIs because mod_dir will add it automatically (as long as DirectoryIndex is set properly).

See also "Cool URIs don't change".
 
Last edited:
Top