Simple Expand/Collapse for the Quick Launch in SharePoint 2013 or SharePoint Online

Yesterday I helped my pal Marcel Meth (@marcelmeth) with a pretty simple little task, but everything’s simple if you know how to do it! We needed to add simple accordion-like expand/collapse functionality to the Quick Launch on the pages in a Site Collection. Because there were going to be a lot of links in the Quick Launch (mostly links to different views of lists), it was getting pretty cumbersome to wade through. By adding this expand/collapse capability, we could improve the user experience (UX). It’s little stuff like this that makes SharePoint usable. Never underestimate the power of a small tweak like this.

This code works on a Team Site on SharePoint Online in Office365 with its Quick Launch exposed in the normal way. Any other customization you have in place may interfere with this working. (Yadda, yadda, disclaimer, YMMV, etc.) I’m sure it will work for you – possibly with some tweaks – in any SharePoint 2013 or SharePoint Online site. You can add this script to a single page or to the master page if you’d like it to work on all pages in the Site Collection.

// Find all the top level links in the Quick Launch that have children
var topLevelLinks = $("div[id$='QuickLaunchMenu'] > ul > li:has('ul') > a");

// Prepend the little "twiddle" icon to each top level link
topLevelLinks.prepend("<span class='ms-commentexpand-iconouter ql-icon'><img alt='expand' src='/Comm/Comms2/_themes/1/spcommon-B35BB0A9.themedpng?ctag=2' class='ms-commentexpand-icon'></span>");

// We're starting with all of the sections collapsed. If you want them expanded, comment this out.
topLevelLinks.closest("li").find("> ul").hide();

// Set up for the click even of on the top level links
topLevelLinks.click(function(e) {

  // We're going to stop the default behavior
  e.preventDefault();

  // Find the elements we need to work with
  var childUl = $(this).closest("li").find("> ul");
  var isVisible = childUl.is(":visible")

  // If the section is visible, hide it, and vice versa
  if(isVisible) {  

    // Replace the icon with its antitheses
    $(this).find(".ql-icon").replaceWith("<span class='ms-commentexpand-iconouter ql-icon'><img alt='Expand' src='/Comm/Comms2/_themes/1/spcommon-B35BB0A9.themedpng?ctag=2' class='ms-commentexpand-icon'></span>");
    // Hide the child links by sliding up. Note: You could change the effect here.
    childUl.slideUp();

  } else {

    // Replace the icon with its antitheses
    $(this).find(".ql-icon").replaceWith("<span class='ms-commentcollapse-iconouter ql-icon'><img alt='Collapse' src='/Comm/Comms2/_themes/1/spcommon-B35BB0A9.themedpng?ctag=2' class='ms-commentcollapse-icon'></span>");
    // Show the child links by sliding down. Note: You could change the effect here.
    childUl.slideDown();

  }

});

Similar Posts

30 Comments

  1. Hi Marc,

    Just an aside, this seems to need the Site Collection Publishing feature to be switched on to give you the Navigation menu option rather than the individual quick launch. It would appear the two options have a different layout on the page.

    Paul.

      1. It’s weird, I can’t see any difference in the markup, but it didn’t work until we enabled Publishing at the site collection level so that we added links through the Navigation link, then it started working.

        I’ve just tried it in another site and it’s working on everything but the Recent link… That said, Activating the Publishing feature is not behaving as it should.. I shall keep digging 8-)

          1. In the case we were working with, we didn’t care about the Recent link so much, so we probably just didn’t notice it. We were really after collapsing a bunch of relatively long lists of links to views we were creating.

            As with all things like this, YMMV! Thanks for the info on the difference, though. I’m sure it may help others.

            M.

  2. For one who does not a single thing about jQuery, do you simple copy and paste this into a script editor on a page or am i missing something?

    1. Chris:
      I’d suggest creating a file and referencing it in a Content Editor Web Part (CEWP). However, you’ll also have to determine if you need to add a reference to jQuery. It’s possible that it’s already loading in the master page or some other way. Check with whomever manages those aspects of your environment.

      M.

      1. I’m using Sharepoint that’s part of Office 365 and not sure what steps to take when applying the code in order to modify the Quick Launch. I’m a beginner with Sharepoint and need help if possible on the specific steps I need to take to implement this code. Just adding a CEWP to a page and pasting the code doesn’t work. I pasted the code in a text file and uploaded the file to Sharepoint and tried referencing the file link but doesn’t work. The steps are not obvious from my end. Any help would be appreciated.

  3. Hi Marc,

    Awesome post! Very much enjoying the solution, but had to adjust it a bit for my main stakeholders use case in that the headings needed to be functional links. I attempted to adjust the code as below, and while it works it does not do so very well from a look and feel perspective. Would you suggest I rewrite the entire function, or does it make sense to set up the events in a different way? My jQuery-fu is not so strong yet :)

    $( document ).ready(function() {

    // Find all the top level links in the Quick Launch that have children
    var topLevelLinks = $(“div[id$=’QuickLaunchMenu’] > ul > li:has(‘ul’) > a”);

    // Prepend the little “twiddle” icon to each top level link
    topLevelLinks.prepend(“”);

    // We’re starting with all of the sections collapsed. If you want them expanded, comment this out.
    topLevelLinks.closest(“li”).find(“> ul”).hide();
    topLevelLinks.each(function(){

    var link = $(this).attr(‘href’); // get link from heading
    $(this).children(‘span.additional-background.ms-navedit-flyoutArrow’).attr( “href”, link ); //apply the href attribute to the span containing the name of the navigation item.
    $(this).children(‘span.additional-background.ms-navedit-flyoutArrow’).css( “cursor”, “pointer”); //bad fix to avoid the underline behaviour caused by the alterations (looks like basic hyperlink on mouse over)

    $(this).children(‘span.additional-background.ms-navedit-flyoutArrow’).click(function (f){
    f.stopPropagation();//prevents opening of the accordion if intent to navigate so if you click on the text the event to expand the menu does not fire
    var link2 = $(this).attr(‘href’);
    window.location = link2; // this could probably be done better :)
    });

    $(this).removeAttr(‘href’);

    });

    // Set up for the click even of on the top level links
    topLevelLinks.click(function(e) {

    // We’re going to stop the default behavior
    //e.preventDefault();

    // Find the elements we need to work with
    var childUl = $(this).closest(“li”).find(“> ul”);
    var isVisible = childUl.is(“:visible”)

    // If the section is visible, hide it, and vice versa
    if(isVisible) {

    // Replace the icon with its antitheses
    $(this).find(“.ql-icon”).replaceWith(“”);
    // Hide the child links by sliding up. Note: You could change the effect here.
    childUl.slideUp();

    } else {

    // Replace the icon with its antitheses
    $(this).find(“.ql-icon”).replaceWith(“”);
    // Show the child links by sliding down. Note: You could change the effect here.
    childUl.slideDown();

    }

    });
    });

  4. Hi Marc,

    I can’t get the small + and – icons to appear between the > and the Quick Launch menu item.

    Coud you please provide some guidance.

    Henric

    1. Hi again,

      Never mind, I found that I had the wrong URL to spcommon file. With the right one I got a small triangle pointing to the right and when expanded a filled triangle pointing down-right.

      Thanks for a nice solution to a problem that should have a built in functionality.

      Henric

  5. Hi Marc,

    Great post.

    Do you know if it’s possible to have the .menu-item-text be made an anchor for reaching the parent site when clicked, whilst .ms-core-listMenu-item would still activate the accordion when clicked (without loading the parent site)?

    Thanks
    Steve

  6. post is great. any one help to modify this script when i click to parent menu until i am inside child menu i want to keep open child menu.. because user when click to next child its collapse. it collapse when user click on other parent any idea

  7. Hi Marc,
    at Unity Connect you showed a way to do this with only CSS. I can not find the code anywhere, can you give us a link?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.