concrete5 SooperFish drop down navigation

Creating a drop down navigation is an old technique by now but it’s still used in a lot of cases to hide parts of a navigation. In addition to the plain CSS menu I wrote more than 2 years ago, I decided to write a new tutorial which uses JavaScript as well. You might ask why: Avoiding JavaScript is nice but creating something as complex as a drop down navigation without any JavaScript leads to a few ugly work arounds. You’ll also have some difficulties to add a fade out and fade in effect unless you’re using CSS3 which isn’t well supported yet.

But at the end it’s up to you, both solutions can work just fine!

Using SooperFish is also a bit easier for us, you’ll see at the end of the tutorial how little code you needed.
At the end your navigation can look like this:

Prerequisite to create your drop down menu

It’s rather simple, the only thing you need is the jQuery drop down plugin called SooperFish. You can find a link to download it on this page: http://www.sooperthemes.com/open-source/jquery/jquery-sooperfish-dropdown-menus.

Once you’ve got the ZIP file, extract all the files into a folder of your choice, we’ll later use some (not all) files from it.

Creating a new block template

If you worked with concrete5 before you’ll probably know that you should never modify any files located in the “concrete” directory. It’s part of the CMS core which gets overwritten whenever you update to a newer version of concrete5. Luckily this isn’t necessary for lots of things! We can easily create an addon, or a block template in this case, without touching the core at all.

In the root of your website, open the folder called “blocks” and go though these steps:

  • Create a folder called “autonav”
  • Within “autonav”, create a folder called “templates”
  • Within “templates”, create a folder called “sooperfish”
  • In the last directory you created, “sooperfish”, create a file called “view.php” and put the following content in it:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
$bvt = new BlockViewTemplate($b); 
$bvt->setBlockCustomTemplate(false);
 
function callback($buffer) 
{
  return (str_replace('class="nav"', 'class="sf-menu" id="nav"', $buffer));
}
 
ob_start("callback");
include($bvt->getTemplate());
ob_end_flush();
?>

Background information about the autonav template view.php

What does this template do?

Since the HTML structure needed by SooperFish is almost identical with the default autonav template, we don’t copy the whole template which would create a lot of redundant information. Instead we include the default template in our new template. However, there are still a few things we modified. The original template has an element like this:

<div class="nav">

but we want this:

<div class="sf-menu" id="nav">

Having this element allows us to use the default CSS files shipped with the Sooperfish plugin. You could modify the CSS files as well and remove all the output buffering functions in the code above.

  • Create another file in the same directory called “view.js” and put this content in it:
1
2
3
$(document).ready(function() {
   $('.sf-menu').sooperfish();
});
  • In the directory where you created “view.php” and “view.js”, create another directory called “js”
  • From the SooperFish ZIP, copy “jquery.sooperfish.min.js” and “jquery.easing-sooper.js” into the “js” directory.
  • On the same level as “js”, create another directory called “css”
  • From the Sooperfish ZIP, copy “sooperfish.css” and “sooperfish-theme-black.css” into the directory called “css”

We’ve already created and copied all the files we need, the only thing we have to do is to make sure our new template is used. Your file structure should look like this now:

Go to your page and start editing the page and modify the autonav block to make these settings:

It’s important that you select “Display all” in both “Sub Pages To Display” and “Sub-Page Levels”. When you work with a JavaScript based navigation you usually print all the items into the HTML output, but hide some of them using JavaScript. Click on Update when you’re done and click on the block you modified again, but this time select “Custom Template” and select “Sooperfish” and click on “Update” again.

Publish the changes and you’ll see your new drop down navigation!




94 Comments

Thanks for this cool tutorial

Its possible to add an “images” folder in the css folder in order to show te arrows for some themes of the menu.

Also, you might choose any of the 4 different css preconfigured files. All that has to be done is putting the sooperfish.css and the sooperfish-theme-xxxx.css in the css folder.

Of course, it is also possible to change some features in the sooperfish.css.

Do you have any idea of how to tweak the behaviors of the javascript animations?

Cheers anyway and give us soon a Jquery “from scratch” Navbar menu tutorial.

Happy New year!

I’m using a preconfigured file already, aren’t I?
good point about adding images in the css directory!

Hi Remo,

Thanks very much for this tutorial. I’m running into one issue I’m hoping you might be able to help me with:

Everything works great if I embed an area in a Concrete5 template and then add the autonav block to it. However, I’d like to embed the block directly in my header template (without creating an area that the nav can be added to / removed from). When I do this, the dropdown effect stops working (also, though less importantly, the little downward-pointing arrow graphic normally displayed with each top-level menu item disappears). The CSS styling (background & border colors, font size, etc.) is still there.

I’m somewhat of a newbie to web development so there could be something simple I’m missing, but I’m having trouble figuring out a fix. Any pointers would be appreciated.

Maggie

I meant to include the code I’m using to embed the block:

$autonav = BlockType::getByHandle(‘autonav’);
$autonav->controller->orderBy = ‘display_asc’;
$autonav->controller->displayPages = ‘top’;
$autonav->controller->displaySubPages = ‘all’;
$autonav->controller->displaySubPageLevels = ‘custom’;
$autonav->controller->divSubPageLevelsNum = ‘1’;
$autonav->render(‘templates/sooperfish/view’);

Hi Maggie,

I’m making some assumptions but this theory would work:

Every block or template in concrete5 can have one or several JavaScript / CSS files. Since these files should be included within the head tag of the document, concrete5 looks for them before the actual block content is rendered.

How does concrete5 look for these blocks? Since everything is database based, it searches for all blocks on the page to be rendered using an SQL query, which then adds the .js and .css files.

However, when you use the code above, which I partially described here: http://www.codeblog.ch/2009/04/concrete5-blocks-within-templates/, concrete5 doesn’t know what blocks will be on that page and can’t include the necessary .js and .css files.

What does this mean? I’d start by looking at all .css and .js files in your block (or template) and add them manually to your theme. As far as I know, there’s currently no way concrete5 could detect them and thus no way around that hard coded part in your theme.

Can you please try that? If it doesn’t work – a link to your website would be helpful!

Thanks

Thanks for the quick reply, Remo!

Unfortunately, the site is in development and I don’t have it uploaded anywhere yet, but I’ll do my best to explain what I’m seeing.

I viewed the source for one of the pages in the site and it looks like the block’s JS & CSS files are getting included in the head section, so that seems ok. I thought maybe some other JS I inserted might be conflicting with that which Sooperfish depends on, so I stripped all of that out, but still no luck. Finally I did a diff of the HTML generated in each of the two cases (I probably should have started there), and noticed this:

When I use the code above to embed the autonav block directly in the template, the sub-pages aren’t printed in the list that’s generated. If I instead add an area to the template, then add the autonav block and configure the same settings via the UI, the sub-pages are printed.

Looking into this even further I found the problem seems to be with setting displaySubPageLevels = ‘custom’ (followed by divSubPageLevelsNum = ‘1’, as I only want to display the top level-pages and one level below). As I mentioned, this works fine when I use the UI to add the block to an area and configure these settings, but doesn’t work when I embed it directly (setting displaySubPageLevels = ‘all’ in the code does work). Puzzling, because ‘custom’ seems to be the same value set via the UI…

Maggie

Hello

Thanks, this was very helpful. However I’m new to website design and my menu doesn’t have the size I want… πŸ™‚
Can you help ? I want to have the menu width to be 100% and all the main menu items to be equal size. How can I do that (with a sooperfish for dummies style please πŸ™‚ ?

I’m sorry but I’m currently caught up in a huge project and don’t have any concrete5 playgrounds nor the time to create a complete solution for you!

Doesnt work on as described on v5.5.

Waste of time, I’ll have to buy the add-on as I dont have more time to waste.

This tutorial has been written using v5.5, I just tested it again and it works fine but please go ahead and buy the commercial add-on! I don’t mind not to have such nice people on my blog who post such really nice comments to motivate me to write and publish more fresh stuff.

I decided to add hoverIntent to this. Found great how-to on Stack Overflow for this at: http://stackoverflow.com/questions/3574001/adding-hoverintent-to-jquery-dropdown

All that is needed is to download the hoverIntent JS file at http://cherne.net/brian/resources/jquery.hoverIntent.html and then use “jquery.sooperfish.js” instead of the minified version. Change [code]$(‘li’, this).unbind().hover(showSooperfishUl, hideSooperfishUl);[/code] to

[code]
$(‘li’, this).unbind().hoverIntent({
over: showSooperfishUl,
timeout: 200,
out: hideSooperfishUl,
sensitivity: 3,
interval: 200
});
[/code]

Hi Remo,

Any idea how I can get the drop down links to stack vertically instead of horizontally? Any help you can provide would be awesome.

Thanks again!

I think most drop down menus should work as long as it is possible to click on the top level item. SooperFish works fine on all my mobile devices!
But nonetheless I wouldn’t recommend using this if your focus is on mobile devices, drop down menus aren’t very common for touch interfaces.

Okay ..thanks

Do you have any Idear what could be a solution when haveing a theme
in Concrete5 with the sooperfish, and maybe using the C5 addon
Mobile Theme Switcher

I’m afraid but I never worked with the mobile theme switcher so far! Do you have any specific problem? I might be able to help if you can give me a few more details.

Hey,
at first, thank you very mutch remo ! great work !

I have only one problem: after putting in the sooperfish navigation my edit menu got at the top of the browser got lost. I don’t know why ? i use the version 5.5.1

Thanks a lot for ur answers!

greez tuna

Hello, Great plugin.
One question!
I would like select the active menu.

i put in sooperfish-theme-black.css
in line 31-35 i add a line. (ul#nav .nav-selected)

ul#nav .nav-selected
,ul#nav li a:hover
,ul#nav li a:focus {
color:#111;
background:#ccc;
}

So now, when I press some page, this menu is selected!

The problem is that if I select a submenu page, only show selected this page, and I would like to show the page and the menu.
*for example:

Animals
-lion
-dog
-cat

I would like that when i press in dog, select dog and Animals!!!

Any idea??

Have a look at the markup generated by the template, there’s usually nav-path or nav-path-selected. I always recommend to use a tool like FireBug, you know about it?

Simply install it and inspect the element you want to style and you’ll see the CSS classes assigned to it, make web development a lot easier!

Remo, you are a gentleman! Works great, much better than the example in the only concrete5 book there is to buy (which doesn’t seem to work at all…). Comments from Tom above are a disgrace. You supplied something that everyone else seemed to get to work, completely free of charge and in your own valuable time. Guys like that will never amount to much.

Thanks so much, you’ve got me right out of a hole!

Thanks a lot! I really appreciate it! However, there’s one thing I have to tell you: I wrote that book πŸ˜‰ I’m aware that the lightbox example doesn’t work but there should be an errata in the book about it. If there’s anything else which doesn’t work, please send me as many details as possible – the code you have, a copy of the error message and I’ll look into it!

Hi Eric, there are several options for this but only one I can think of without creating a new autonav template or modifying the SooperFish scripts. It doesn’t exactly do what you wrote, instead if links to the first sub page. In your case, clicking on “About” would navigate to “Our Team”, you basically have two links with a different text but the same target.

If that’s okay as well, check the message by jordanlev on this page: http://www.concrete5.org/community/forums/usage/auto-nav-options/ You have to create a new attribute and tell the “About” page to link to the first child. I think it should be pretty clear what you writes..

I could give you a few hints to make the parent links non-clickable but that’s only going to work if you know a bit about PHP and the concrete5 framework.

Hope this helps!
Remo

It’s not perfect but you can use this SooperFish navigation template, just make sure that you only display the top level when adding the autonav block.

Hey Remo! Great tutorial! I was wondering is there a way to adjust the speed of the drop down from the default settings?

Thanks for such a great tutorial!

Any reason why I’m getting this error in my console?

TypeError: ‘undefined’ is not a function (evaluating ‘$(‘.sf-menu’).sooperfish({
delay: 50,
speedShow: 50,
speedHide: 50
})’)

I have the following in my view.js…

$(document).ready(function() {
$(‘.sf-menu’).sooperfish({
delay: 50,
speedShow: 50,
speedHide: 50
});
});

There are a number of reasons why this can happen. It might be because you’re using another library (mootools) im combination with jQuery.

This could be fixed by using jQuery instead of $ to access the jQuery methods. Wrap it in something like this:

(function ($) {
$(document).here-goes-your-init-stuff.;
}(jQuery));

Most likely it’s because there’s a missing library or one that’s interfering with jQuery. I’d start by wrapping, removing and then adding some JavaScript libraries. If you get closer to the problem, I could probably give you a more precise answer as well!

If I comment out my view.js file it still works fine and doesn’t throw the error… I only am loading query onto the page. Is the view.js not necessary for the drop downs to work?

Hmm.. view.js is necessary because this file is responsible for the SooperFish initialization. If it still works you probably have another JavaScript on that side..
Are there any other JavaScripts? Maybe from different add-ons? Can you remove them to see if anything causes the problem?

Bryan, I had a look at the link you’ve sent me. The drop down still works in your case because the sooperfish.css does have some basic drop down functionality for modern browsers in it. You won’t get any kind of animation which you’d get by using the JavaScript, but it still works.

I also noticed, that you’re including jQuery twice. Once in the head and once at the bottom of your document. I highly recommend to avoid this! This could also cause some unexpected effect like you where having with the SooperFish JavaScript.

Please check your theme and remove all unnecessary includes and see if your problems goes away.

Remo,

Great tutorial, thanks. I am a newb at both concrete5 and development, design, etc. I have followed the instructions carefully and now my top level pages all have errors or like my home page, display the layout incorrectly.

When I try to get my js files from the directories, I receive an error and they will not open.

Apologies if you have already covered this and I overlooked it but any assistance would be appreciated.

Love the drop down menu by the way, it’s absolutely necessary for what my site provides.

Hi Michelle,
could you post the complete error message somewhere? There are almost an infinite number of possibilities, having an error message would help to reduce this number πŸ˜‰
Thanks,
Remo

Thanks for the prompt response. I would be happy to upload you a screenshot of the error.

1. jquery.easing-sooper.js
(jquery is undefined)

2. jquery.sooperfish.min.js
(‘$’ undefined)

3. view.js
(‘document’ undefined)

Some of the pages the menu works but the layout is way off. Others are fine. I’m sure I am missing something but appreciate your assistance.

Leave a Reply

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