1,804 articles and 15,671 comments as of Tuesday, December 28th, 2010

Wednesday, December 3, 2008

JQuery for Everyone: Accordion Left Nav

Last night, I set out on a mission; a mission to create an accordion-style left navigation menu for my WSS test site.  Mission complete.  If you can copy/paste, you can see it in action.  Since I used Google’s API to load jQuery, you don’t even need to download the library file.

First, look at your left nav.  If you changed it from the out-of-the-box setup, make sure you have “headers” and “submenus” that make sense.  For example, Documents should appear on top of a bulleted list of document libraries.

Obviously, if you want the accordion-style menu for all pages, you should work it into the default.master.  For now, we can work with a test page by adding a Content Editor Web Part (CEWP) to the page.  Add the code below to the web part’s Content Editor (source).  Now your menu should look like this.

When you click on the menu header box with the down arrow image, it exposes the submenu below it and swaps the image with an ‘x’.  Likewise, clicking the header with the ‘x’ will hide the associated submenu.

Here’s the code:

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  // Load jQuery
  google.load("jquery", "1.2.6");
</script>
<script type="text/javascript">
$(function(){
//initialize menus
    var menuRows = $("[id$='QuickLaunchMenu'] > tbody > tr");
    var menuHd = menuRows.filter("[id!='']:has(+tr[id=''])");
    //set img path for when submenu is hidden
    var closedImg = "/_layouts/images/Menu1.gif";
    //set img path for when submenu is visible
    var openedImg = "/_layouts/images/ptclose.gif";
    var cssInit = {
        "background-image": "url('"+closedImg+"')",
        "background-repeat": "no-repeat",
        "background-position": "100% 50%"
    }
    var cssClosed = {"background-image": "url('"+closedImg+"')"}
    var cssOpen = {"background-image": "url('"+openedImg+"')"}
    //hide submenus
    menuRows.filter("[id='']").hide();
    //apply initial inline style to menu headers
    menuHd.find("td:last").css(cssInit);
    menuHd.click(function () {
        var styleElm = $(this).find("td:last")
        var nextTR = $(this).next("tr[id='']");
        if (nextTR.is(':visible')) {
            nextTR.hide();
            styleElm.css(cssClosed);
        } else {
            nextTR.show();
            styleElm.css(cssOpen);
        }
    });
});
</script>
View all entries in this series: PaulGrenier-JQuery for Everyone»
Entries in this series:
  1. JQuery for Everyone: Accordion Left Nav
  2. JQuery for Everyone: Print (Any) Web Part
  3. JQuery for Everyone: HTML Calculated Column
  4. JQuery for Everyone: Dressing-up Links Pt1
  5. JQuery for Everyone: Dressing-up Links Pt2
  6. JQuery for Everyone: Dressing-up Links Pt3
  7. JQuery for Everyone: Cleaning Windows Pt1
  8. JQuery for Everyone: Cleaning Windows Pt2
  9. JQuery for Everyone: Fixing the Gantt View
  10. JQuery for Everyone: Dynamically Sizing Excel Web Parts
  11. JQuery for Everyone: Manually Resizing Web Parts
  12. JQuery for Everyone: Total Calculated Columns
  13. JQuery for Everyone: Total of Time Differences
  14. JQuery for Everyone: Fixing Configured Web Part Height
  15. JQuery for Everyone: Expand/Collapse All Groups
  16. JQuery for Everyone: Preview Pane for Multiple Lists
  17. JQuery for Everyone: Preview Pane for Calendar View
  18. JQuery for Everyone: Degrading Dynamic Script Loader
  19. JQuery for Everyone: Force Checkout
  20. JQuery for Everyone: Replacing [Today]
  21. JQuery for Everyone: Whether They Want It Or Not
  22. JQuery for Everyone: Linking the Attachment Icon
  23. JQuery for Everyone: Aspect-Oriented Programming with jQuery
  24. JQuery for Everyone: AOP in Action - loadTip Gone Wild
  25. JQuery for Everyone: Wiki Outbound Links
  26. JQuery for Everyone: Collapse Text in List View
  27. JQuery for Everyone: AOP in Action - Clone List Header
  28. JQuery for Everyone: $.grep and calcHTML Revisited
  29. JQuery for Everyone: Evolution of the Preview
  30. JQuery for Everyone: Create a Client-Side Object Model
  31. JQuery for Everyone: Print (Any) Web Part(s) Plugin
  32. JQuery for Everyone: Minimal AOP and Elegant Modularity
  33. JQuery for Everyone: Cookies and Plugins
  34. JQuery for Everyone: Live Events vs. AOP
  35. JQuery for Everyone: Live Preview Pane
  36. JQuery for Everyone: Pre-populate Form Fields
  37. JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
  38. Use Firebug in IE
  39. JQuery for Everyone: Extending OWS API for Calculated Columns
  40. JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
  41. JQuery for Everyone: Email a List of People with OWS
  42. JQuery for Everyone: Faster than Document.Ready
  43. jQuery for Everyone: Collapse or Prepopulate Form Fields
  44. jQuery for Everyone: Hourly Summary Web Part
  45. jQuery for Everyone: "Read More..." On a Blog Site
  46. jQuery for Everyone: Slick Speed Test
  47. jQuery for Everyone: The SharePoint Game Changer
  48. JQuery For Everyone: Live LoadTip
 

Please Join the Discussion

93 Responses to “JQuery for Everyone: Accordion Left Nav”
  1. Kanwal says:

    Mark, great post. I have done this for two clients. Integration of SharePoint navigation with jQuery.

    If your visitors would like to expand the menu with a mouseover rather than click, change the following line:

    menuHd.click(function () {

    to the this:

    menuHd.mouseover(function () {

    This code doesn’t provide the best behavior, as you need to workout all possibilities, but it does open user minds to what is possible. I will be starting a blog focused on branding SharePoint, that will help designers / developers alike.

  2. Actually, the article is by Paul, moderator of Stump the Panel, but I’ll take credit if you’d like. Nice job, Paul… potential workshop material. — Mark

  3. eric says:

    This is great!

  4. Robin says:

    2 Thumbs Up!

  5. Really amazing stuff. Not so much what it does but how simple it is to do it.

  6. Chris says:

    This is no longer necessary with jQuery UI.

  7. AutoSponge says:

    @Chris,

    jQuery UI’s accordion (from what I’ve seen) is based on a predictable or classed DOM.

    I know you’ve peaked under the hood–SharePoint is anything but pretty in the dynamically generated left nav.

    It’s a minefield of nested tables, id/classless elements, and kludgey CSS. Since we don’t have control over the HTML OOB, I don’t think jQuery UI makes this process easier.

  8. Chris says:

    Hey Paul,

    I didn’t mean to demean your work. This is impressive jQuery from one jQuery’er to another. You can specify markup to be used such as:

    $(”div#my_accordion”).accordion({ header: “h3″ });

    You’re right though that sometimes it’s easier just to use the horrendous markup SP sends to the browser. If someone asked me to do an accordion I’d make them use the CSS Friendly Adapters.

  9. MOSSLover says:

    This post looks a little cleaner than the version I created with a co-worker several months ago at my old job. I think I’m going to give it a try on my VPC sometime in the next few weeks. Good job Paul!

  10. Ari says:

    How would the code look like if the Google API would not be used? Installed the jQuery for SharePoint from http://www.codeplex.com/smarttools

  11. youugyz says:

    This is great.. since it easy way to make accordion menu..

    somebody know how to show/expand the menu from begining?

  12. AutoSponge says:

    @Chris,

    I forgot to mention, another issue I found with the WSS DOM and jQuery: if you use slideToggle (as I did originally), FireFox reduces the width of the toggle’d element. This causes the border-top to shrink and the “lines between menu options” gets funky. I figured out it’s because slideToggle makes elements visible with display=”block”.

    I see that as an error, it should be display=”" which is what show() does. Without testing, jQuery UI may have the same problem since I’m sure it uses slide or some other animation combination.

    (To demonstrate, you can probably replace show/hide with slideToggle in the script above).

    Let me know if you find out that jQuery UI doesn’t do this, I’m always interested in learning new ways of doing things.

    Thanks,
    Paul

  13. Chris says:

    Paul,

    Well without looking at I know that similar behavior happens when the toggled element has padding on it. That’s why you nest the toggled element in another element.

    Article

    Is that not what you’re referring to? Also, jQuery UI are just bits of functionality built on top of the API. This sounds like an issue with the standard API.

  14. AutoSponge says:

    @Chris,

    That’s good to know. The elements I’m talking about do have padding but I think this hint refers to problems when you hide the element. In this case, the problem occurs when you hide then expose (since I hide onLoad, making a submenu visible shows the problem).

    If this is a problem with the core API, someone much smarter than me will have figured it out. Maybe there’s a reason slideToggle displays “block.” *shrug*

  15. AutoSponge says:

    @Ari,

    I think the smarttools option adds the script library to your master pages, so you probably don’t need the top 5 lines of that script. Check your page source to see if “jquery” appears in a script tag anywhere to make sure.

  16. AutoSponge says:

    @youugyz,

    I’m not sure what you mean. However, if you want to start with all of those submenus visible, take out the line under //hide submenus.

  17. Kirsten Coeur says:

    Hi Paul,

    I’m so thrilled with your tip! I’ve been wishing I could do this with my menus. I wonder, can you tell me how I might get rid of the warning, “This page contains both secure and nonsecure items.” I copied the file “jsapi” into my document library and linked to it from my web part to see if that would eliminate the warning message, but maybe there is another step? I am not a programmer (other than some html) and am not familiar with jQuery. Maybe I just have to live with the warning message – it’s worth it for the accordion menu. :-)

  18. Kirsten – Let me jump in and help Paul on this one because I already know your environment.

    The security warning pops up because the script is pointing outside your local environment, which is a secure server (https), to the google API script. To get rid of the security warning, download the jQuery script, install it in a document library on your site and then replace the call to the google javascript with the location of your script.

    Now you’re pointing locally and this will do away with the security warning.

    Mark

  19. Chris says:

    Mark – or you could change your IE security settings. If you’re getting that message chances are you’re missing out on a lot of content.

    But you’re right on the best approach.

  20. AutoSponge says:

    @Kristen,

    Great question. The warning comes from “mixed content” (both SSL and non-SSL) on the page. For an SSL site, you should use the copy of jQuery in your local library replacing the SRC in the first SCRIPT tag. Then delete the second SCRIPT tag (4 lines).

    Let me know how it goes,
    Paul

  21. Kirsten Coeur says:

    Thanks to all three of you for your responses – and so timely! I had already changed the SRC in the first SCRIPT tag so that it was pulling from my local library, but didn’t know I needed to delete the second SCRIPT tag. So, now it works beautifully. Thanks a million, Paul!

    Best regards,
    Kirsten

  22. steve0 - Sharepoint Beginner says:

    I really appreciate the work that you have done with the Accordian Left Nav and its GREAT!!!! I am currently using this in one of my Sharepoint portals. My question is how do you keep the menu expanded for a menu item when its clicked. How would this be written in jQuery. I have tried and have had no luck. You help would be very much appreciated.

  23. Bobby says:

    I wanted this to behave a bit more like Outlook and only allow one menu to be expanded at a time so I added the following after the } else {

    menuRows.filter(”[id='']“).hide();
    menuHd.find(”td:last”).css(cssClosed);

    May not be the best way to do it since I am just learning jquery but it does work for me atleast

  24. AutoSponge says:

    @Bobby,

    That’s great! My examples are intentionally simplified. I learned JavaScript over the last year and jQuery in only the last couple of months by studying real-life examples. If you can take my examples and make them your own, you’re quickly learning this stuff–and that’s exciting.

  25. Richard Duffy says:

    I have been trying to insert this code into the default.master page, but nothing seems to be happening.

    Where (between which lines of code) would I need to insert the script?

  26. AutoSponge says:

    @Richard,

    Right after <asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

  27. Richard Duffy says:

    I inserted it into default.master where you instruct, but it only does it for the home page, not on any other pages – am I doing something wrong?

  28. AutoSponge says:

    @Richard,

    Can you tell me how you’re doing the edits?

  29. Richard Duffy says:

    Hi,

    I am using SharePoint Designer to make the edits. I made a copy of the default.master before doing any changes and can make it work for the homepage but not for any other pages in that site collection.

    I have tried this on our live environment, and on a private testing environment, but to no joy!

  30. AutoSponge says:

    @Richard,

    It could be a publishing thing.

    However, for a global change (and to keep your .master page out of the database), you may want to add this to your .master page in the file system.

    Copy the file first to make a backup. Then edit the file in any text/html editor (opening it from Open > Site in SPD will not work on the file system file, it creates a copy that goes into the database).

    Try this on your test environment first. And revert the changes from SPD (that will overwrite the changes to the file system).

  31. Cimares says:

    Paul,

    I’ve placed your block of code onto my default.master and it works beautifully all the time my VPC can see the net and can use google.

    As most of the time, I’m not working on a network connection, I’ve downloaded jquery-1.3.1.js and added a reference to it in my masterpage and removed the top 5 lines. This is working fine as if I add a document.ready function to trigger an alert, I see my alert pop up.
    It does however stop the accordion behaviour. Any ideas or a pointer on troubleshooting?

    Paul.

  32. AutoSponge says:

    I had to update the web part’s code for jquery 1.3. Where I used (”[id='']“) change it to (”:not([id])”) and where I used (”[id!='']:has(+tr[id=''])”) change to (”[id]:has(+tr:not([id]))”)

    I think that’s all the changes.

  33. Bill says:

    Of note: this doesn’t appear to work with the downloaded version of jquery 1.3.2. I had it installed in a document library and properly referenced but the menu wouldn’t expand. When I used version 1.2.6 I had no problems.

  34. Tony says:

    Hi Bill. I noticed the same thing. Version 1.3 or later and the menu headers display properly, but they do not open (and assume they do not close, but since can’t open…), even including the changes Paul notes on 6 Feb. [Is that 2 or 3 replacements in the code?? Either way, does not seem to work for me with jquery 1.3]

    Also interesting is that I left in the changes for 1.3 and switched back to 1.2.6 and now it works again (which makes sense, so maybe not so interesting).

    Also, if you add: “cursor”: “hand” to each of the 3 variables cssInit, cssClosed, cssOpen, you’ll get the hand cursor right over the accordian images.

  35. Tony says:

    I’ve seen other posts indicating that the accordian menu and other jquery wifgets don’t play well toegether due to differences in the jquery version. I’m using the preview pane with the accordian, and either one works or the other doesn’t,d epending on which version of jquery I use. If I use 1.2.6, the preview does not work completely (for grouped lists not at all, and the last item on any other list will not preview).

    If I switch to 1.3, then the preview pane works fine, then the accordian menu stops working.

    I can’t figure out the changes for either to get both to work in either version.

  36. Tony says:

    OK, forget trying to debug this. I switched to version 1.3.1, now EVERYTHING works.

  37. Vinny says:

    For jquery-1.3.2, there is a change to how :visibility is reported… change
    if (nextTR.is(’:visible’)) {
    to
    if (nextTR.css(”display”) != “none”) {

    may not be the best way to do it, but it works.

  38. AutoSponge says:

    @Vinny,

    Thanks for the update. I’ve noticed some subtle changes along the way that break stuff. A much of a hassle as that is, it’s still worth it to me in how much faster I can develop solutions.

  39. sarath says:

    Nice tip,

    Is there a way to expand any one region say, ‘Lists’ by default when the page is rendered

  40. AutoSponge says:

    Sarath,

    The simplest way would be to use jQuery’s click method to fire the onclick event for a particular row after the new click event is bound.

    That way, if you later add cookie capabilities like I did, it will also register with other functions.

  41. Jason says:

    How do you fix this so that when you click on one of the links/sub-links, that list is expanded? It seems like it defaults to close. I would also prefer not to use cokkies to achieve this.

  42. AutoSponge says:

    Jason,

    Without cookies, you have to pass a query string parameter that the accordion script watches for and sets the appropriate section to open. If you have the exact same left nav on every site using that .master, you can add the script to the .master and pass an integer that represents the position number of the header in the array of headers. Otherwise, there are no id’s to use, so it means a further customized master.

  43. Jason says:

    Thanks for the reply Auto! Forgive my stupidity, but I have no idea how to do this. Can you show me what and where in the above script I need to add this?

    Lastly, pasting the above code Right after yields nothing. The only way I have been able to get this to work is to paste at top of page before

  44. Jason says:

    Yes we do have the exact same left-side navigation throughout the site. Sorry I got cut off above. I meant to say pasting the above code Right after yields nothing. The only way I have been able to get this to work is to paste at top of page before <HEAD on my master page.

  45. sarath says:

    Auto

    In one of your postings you had included cookie code for Accordian. It works fine as a session based cookie. What should I do to make it persistent cookie? Any pointers will help

    Thanks

    sarath

  46. Kirsten Coeur says:

    Hello all,

    I have followed this thread with interest, thanks to all of you who have contributed.

    Would it be possible to get the code with its various modifications since the first posting in a ‘clean’ version? Not being a programmer, I haven’t been able to figure out why mine is no longer working… I’ve got the newer ‘jquery-1.3.2′.

    Thank you!

  47. AutoSponge says:

    @sarath,
    Good article on cookies: http://www.quirksmode.org/js/cookies.html

    @Kirsten Coeur,
    This is the only published version, the other version was only released to those attending the workshop.

    @Jason,
    Check out Tony’s article for .master changes: http://www.endusersharepoint.com/?p=1468

    If you use the cookies, setting a section to click on load will open OR close depending on the cookie state. If you’re using cookies, you need to check for visibility before you click.

  48. Jason says:

    Quote: “Without cookies, you have to pass a query string parameter that the accordion script watches for and sets the appropriate section to open. If you have the exact same left nav on every site using that .master, you can add the script to the .master and pass an integer that represents the position number of the header in the array of headers. Otherwise, there are no id’s to use, so it means a further customized master.”

    Can you show me how to go about accomplishing this, and where in the script to add it to? We do have the same left navigation throughout the entire site. Thanks for you help so far btw- we’re almost there!

  49. sietse says:

    Hi,
    Great script!!
    Is it possible to let the script “remember”the last menu item a user has opened?

    hope u can help me!

    thanks

    Sietse

  50. AutoSponge says:

    @sietse,

    Check out the more recent article: http://www.endusersharepoint.com/?p=1640

Trackbacks

Check out what others are saying about this post...
  1. SharePoint Daily for December 4, 2008…

    Top News Stories Microsoft Puts Datacentres on Wheels (ZDNet) In a blog posting on Tuesday, Microsoft…

  2. [...] JQuery for Everyone: Accordion Left Nav : End User SharePoint [...]

  3. SharePoint Kaffeetasse #98…

    Tools und Addons Custom Content Editor Web Part for SharePoint jQuery http://jquery.com/ jQuery is a…

  4. OneOfSix says:

    Add Links to SharePoint Wiki Toolbar using jQuery…

  5. [...] Es muy interesante resisar el código fuente y el uso que se hace de la tecnología jQuery(un breve ejemplo de jQuery para personalizar la barra QuickLanch se puede ver en:JQuery for Everyone: Accordion Left Nav) [...]

  6. SharePoint QuickLaunchExtender…

    Codeplex sigue siendo un lugar para encontrar cosas interesantes para SharePoint:-), QuickLaunchExtender…

  7. WSS 3.0 & MOSS: Recopilatorio de enlaces interesantes (XXVI)!…

    Siguiendo con la tradición, una vez más os presentamos el clásico recopilatorio de recursos, enlaces…

  8. [...] JQuery for Everyone: Accordion Left Nav. Fuente: EndUser SharePoint.com. [...]

  9. [...] I enjoyed them all and learned a lot from our users. One of the more popular solutions, based on Accordion Left Nav and featured in Tony’s Deployment article, has only one improvement since the original [...]

  10. [...] JQuery for Everyone: Accordion Left Nav [...]

  11. [...] [Solution] JQuery for Everyone: Accordion Left Nav [...]




Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!