Concrete5 quick accordion menu in five minutes

I love using Concrete5 as a CMS as it is just so easy to work with.  The task of extending or customising a website and it’s functionality is actually a pleasure rather than a really daunting task as with some other CMS.

Recently I had a requirement to build an accordion style main-navigation for a new website I’m building with Concrete5.  This can be achieved very easily – the post below probably makes long work of everything but all you need to do to accomplish this is 2 minor file edits and one file upload – explained below.

Out of the box the auto-nav block in concrete5 renders a nested unordered list <ul> containing the various levels and sublevels of pages that you specify when you add the block to a page.

Using an unordered list is a pretty standard way of handling website menus because it lends itself well to styling and manipulating with javascript.

First I create the autonav block in my C5 website.

Next we choose the navigation parameters – we want to show all levels from the top down.

Once we’ve set those options, clicked add and then saved the page we should have a nested unordered list with all of the sublevels expended- something along the lines of this.

As we can see this is completely unstyled and is just using default styles, indentations etc and is fully expanded to show the levels we selected.

So – we have our navigation element and it contains all of our pages – how easy was that?  What we want to do though is make an accordion style menu to that the sub-levels slide out when clicked on.  We need some javascript to accomplish this.

Luckily Concrete5 is loaded up with JQuery by default so we don’t need to add any code to call it.

Being the lazy type, wanting to get this done quickly and fully embracing the open style of the web I just googled ‘Jquery accordion menu’ and chose a short piece of code that does the job.  Full kudos goes to Marco at http://www.i-marco.nl/weblog/ for providing this code on his website for all to use:

***** Javascript below *********

/*
Simple JQuery menu.
HTML structure to use:

Copyright 2007-2010 by Marco van Hylckama Vlieg

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();});

***** Javascript above ********

So how do we get this to work with our navigation element in Concrete5.

The answer is – very easily.

From the javascript above I can see that the slide out functionality applies when a <ul> is classed ‘acitem’.

Therefore I need each nested <UL> element in the Concrete5 auto-nav to have this class.

Concrete5 is built to be easily customisable and also very extensible. 
Now I know from investigating the auto-nav block that the code is contained in /public_html/concrete/blocks/autonav.

Investigating the code shows me that the nested menu is generated in /public_html/concrete/blocks/autonav/view.php.

Now here follows one of the clever features of Concrete5 – I do not need to mess around with the core code.
Concrete5 uses an override system.  Under the site root there are duplicated the sub-folders that appear under public_html/concrete/.

Example is probably the best way to show how this works so in /public_html/blocks I replicate the autonav folder

I now have:
/public_html/blocks/autonav
and
/public_html/concrete/blocks/autonav

I copy
/public_html/concrete/blocks/autonav/view.php
to
/public_html/blocks/autonav/view.php

(*note that I do not need to copy all of the files under /public_html/concrete/blocks/autonav – just the one I am changing).

so I can now make changes to my copy of view.php, they will be reflected in the website but the core concrete5 code is unchanged.

The code change in view.php is super-simple – just find the following code block:

   $thisLevel = $ni->getLevel();
   if ($thisLevel > $lastLevel) {
    echo(“<ul>”);
    and change the code indicated bold above to
   echo(“<ul class=”acitem”>”);

Then save view.php

Our Javascript file menu.js also needs a little edit to make everything work properly. 
We just need to change the last line:

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

to read

$(document).ready(function() {$(‘.nav’).initMenu();});

so that it works with the standard Concrete5 .nav class.

If all of the files are loaded to the relevant places and the new menu.js (containing the amended javascript) is called into our page then we know have a sliding accordion style navigation menu.

Voila!

Concrete5 declares classes for styling parts of the autonav – you can see those easily in your view.php.
Other stylings can be done by styling the <ul><li> etc etc in your stylesheet to create indentations etc so you can carry on with your web design as you would do normally.

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

About Andy

Owner at Webcentric web design near Cambridge in the UK. At the moment most interested in Concrete5 CMS, alternate webservers to Apache - especially Cherokee, pdo, sqlite and other databases, JQuery, emerging technologies and website performance.

18 Responses to “Concrete5 quick accordion menu in five minutes”

  1. thanks for taking the time to write this up! If you haven’t already you should submit this to our how-to section on http://concrete5.org

  2. thanks Franz – will do…

  3. Such a well written post.. Thnkx for sharing this post!

  4. Well thought out article. You have a good opinion on the subject and I will be subscribing to your RSS and hope you shall post again soon on similar subjects. But I was would like to know what your sources for the post are? Thanks

  5. Very effectively written information. Will probably be helpful to anyone who usess it, including myself. Sustain the nice work – for certain i will try more posts.

  6. Hi! Would you mind if I share your blog with my zynga group? There’s a lot of people that I think would really enjoy your content. Please let me know. Many thanks

  7. Please let me know if you’re looking for a article writer for your site. You have some really great articles and I believe I would be a good asset. If you ever want to take some of the load off, I’d really like to write some content for your blog in exchange for a link back to mine. Please send me an e-mail if interested. Kudos!

    • Hi,
      sure – if you’d like to write a guest post in return for a link back that’d be great. It’ll need to be on some area of web design though and will need to be written in a similar style to our other posts. Send me another message with your idea…

  8. I couldn’t have really asked for an even better blog. You’re available to present excellent tips, going straight away to the point for simple understanding of your subscribers. You’re undoubtedly a terrific expert in this matter. Thanks a lot for remaining there for folks like me.

  9. Beautiful post bud, I really took pleasure in this blog. I’ll be sure to talk about this to my brother who would, odds are, like to drop by this page too. Found your blog post through the AOL search engine by the way, if you were wondering :P . Good stuff bro.

  10. Some genuinely fantastic work on behalf of the owner of this internet site , utterly outstanding articles .your link on my blog here http://tinyurl.com/page-id-9 ,

  11. I’ve bookmarked http://www.webdesignblog.org.uk/2011/03/concrete5-quick-accordion-menu-in-five-minutes/ at Reddit.com so my friends can see it too. I used Concrete5 quick accordion menu in five minutes | web design blog so it was a good title.

  12. Many thanks for a great weblog write-up, exactly where will you uncover all your info?

  13. Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.

  14. Aw, this was a very nice post. In idea I want to put in writing like this additionally – taking time and actual effort to make a very good article… however what can I say… I procrastinate alot and under no circumstances seem to get one thing done.

  15. Hey,

    thanks for the nice tutorial!
    unfortunately i get an t-string error

    Parse error: syntax error, unexpected T_STRING in /blocks/autonav/view.php on line 41

    the line looks like that:

    $thisLevel = $ni->getLevel();
    if ($thisLevel > $lastLevel) {
    echo(“”);
    } else if ($thisLevel < $lastLevel) {
    for ($j = $thisLevel; $j 1) {

    i added the menu.js into the root folder /js
    in the elements/header.php i included:

    addHeaderItem($html->javascript(‘menu.js’));
    ?>

    that should work, or? is there a way to help me out here?

    thanks, best regards

    Oliver

  16. Does this still work for Concrete 5.5?

  17. can anyone say where we have to put the our new menu.js file?

    tankz in advance……

Leave a Reply

*