These looked like a cool and simple thing to reproduce, so I gave it a shot and came up with something that I think works pretty nicely.

It wasn’t as simple as I thought, and I don’t think my code is the greatest, so I’m open to suggestions. I think this could form the basis for a jQuery plugin but I’ve never created a jQuery plugin so I’m holding off on that for now.

Here’s the demo link if you want to view it before reading the description below:

Features of the Drop-Down Menus

Instead of being positioned absolutely with z-index to overlay the content below, each menu slides down and pushes the rest of the content down with it

The content in each menu is loaded with Ajax

Once opened, the functionality is much like a tab switcher

There are no non-mega drop-downs mixed in, so they all work the same way, taking up the width of the entire page, like regular content

The selected menu’s link has an active state

The drop-down menu will not slide up unless the link of the currently-open menu is clicked; if a link of a non-open menu is clicked, the drop-down remains in place, and the content is updated accordingly

As an alternative to clicking the active menu item to slide up the drop-down, there’s a “close” button in the top right corner, much like you’d see in a lightbox or other modal window

Triangle indicators are present for each drop-down link; the active menu has an upward-pointing triangle indicating “slide me back up”

For my version, the up/down arrows and the “close” link are inserted dynamically with JavaScript; with JavaScript disabled those elements are useless, so the UI stays clean and the top links are still accessible (CBC’s top links are accessible with JS disabled, but the arrows stay in place)

Each menu is populated from an HTML file in a “dropdowns” directory; this is just a simple method to mimic CMS-driven drop-downs — the content can pretty much come from anywhere

You can easily add or remove menu items; just add an associated page in the “dropdowns” menu and link to the page (the link text should have the same name as the file minus the file exension)

Overview of the Code

The code isn’t too hard to figure out. I’m not going to go through it line by line, as in a customary tutorial, but I’ve added comments to the code that describe each major section. Although I have written articles on JavaScript and jQuery, for the most part I only stick to fundamental stuff, so I don’t claim to be a JavaScript expert. So if you have any suggestions for how to improve the code (make it more object-oriented?) I’ll be more than happy to consider and incorporate your thoughts.

I don’t think so, because then you’re loading (in this case) 5 different mega menus that might never be opened. Remember, drop-downs are always optional, not mandatory content. Plus, the way I’ve designed it, the menu content populates the same div element. So to have all of them load would require they be inserted into non-existent DOM elements, or else have separate elements that show/hide (like a tab switcher).

Also, since it’s sliding down, the wait time for the load is about the same as the slide, so the load time is pretty much irrelevant as long as your server load time is fine.

The way this works cannot be done with just CSS. This is not just a regular drop-down menu. Those have been done with CSS, and they work well. This is sort of a combination of mega drop-downs and a tab switcher, just to try something new.

Personally, I don’t particularly think it’s all that great, I just thought it would be something I could try to code.

I agree that JS is the better way here. I think it could be done with CSS3, though, under the following conditions:
1) the content for the mega menus are pre-loaded,
2) the document fragment part of the url (the “hash” part) is not being used by other parts of the page (e.g. no other links using the # sign)

In most real-world applications, imho, these conditions would get in the way and JS would end up being necessary.

Take a look at Snook’s latest diversion for a similar use of the document fragment via the :target pseudo-class: http://ajxn.it/czNztF

Like it, I will have to make something similar for a client’s project I’m working on. However they want actual content loaded instead of links. Not so sure what I think about that, feels kinda weird to me. But it will be fun to make.
Will have to load the content asynchronously as well to avoid a duplicate content penalty.

You might want to go ahead an try and make it into a plugin, it’s surprisingly easy, a lot of fun and great practice.

I was thinking that the best way to ensure SEO is to create the page to use PHP query string values to display the menus. Those values would be found in the HREF for each link like this: “index.html?menu=tutorials”. Then the JS code could use that instead of the page name.

The fallback would be to inject the menus using PHP depending on the query string value. If JavaScript is on, then the query string would never appear. If JavaScript is off, then the page is reloaded and the query string decides which menu is opened.

I think I’ll eventually re-do it to have that feature, otherwise the content in the menus will not be accessible. The same concept could apply to a tab switcher, to make it more accessible.

hi, I have tested this drop menu slidedown and works great, but when i change the file name to .php extension isntead of html, is not showing inside of drop menu is showing blank. is this only works great under html files in dropdown folder!

my php files that i saved in dropdwon folder is comes with jquery code is this mean they blocked to view it in drop menu!

In order for it to pick up PHP files, just go into the main JavaScript file and change the value for the variable “ext” to “.php” instead of “.html”. There are a number of variables you can change in there to suit your needs.

For the menus to open the appropriate content, they get the info from the HREF value of each link. In your example, the HREF value is just “#” so that doesn’t help. You have to create it to insert the correct file names in each HREF, which will then be read by the JavaScript, and the correct content will be opened.

For example, whatever names you have for the menus, you also have to have the same names for the files.

Menus called “resources” and “tutorials” would require the files to be called “resources.php” and “tutorials.php”. Then, the HREF value for “tutorials” would have to be “tutorials.php” in order for it to get the right content.

Are you talking about the demo page on my live site? Or are you talking about the files that you downloaded that you’re trying to view locally?

If you’re trying to view them locally, I believe you have to run them on a local server like Apache in order for the Ajax calls to work. Although I don’t know why it would work in FF. Maybe try uploading to a live directory and see if it works then.

If you’re talking about my own live demo, maybe you can tell me what version of Chrome, because it works fine for me in version 7.0x. Thanks.

Old comment I know but for I fixed this issue with mootools and jquery with
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript">var $j = jQuery.noConflict();</script>
<script src="/templates/new/lib/js/general.js"></script>

Now it works fine and shows the background image but the problem is ajax loading image (loading.gif) is disappeared. I tried to tweak but I couldn’t figure out the reason. If remove the background image then loading.gif starts appearing but I want background image along with loading.gif so kindly tell me, is there a way show loading.gif before background image loads?

We’ve started implementing in a development site (we’re using Zend Framework) and it all seems straightforward. However, the site detects locale and we add a locale identifier into the URL if the site is being viewed from outside the USA. So, in a US browser, the page URL might be something like http://www.domain.com/brand/a. If viewed in a UK browser the same page would have a URL of http://www.domain.com/gb/brand/a.

In a US browser, the megamenus work fine. In a UK browser, they open but we get a ZendController error where the data should be and Zend is objecting to the ‘gb’ in the URL. We’ve tried nearly everything, including stripping out the locale in the .htaccess but we still get the error.

Any ideas why this should happen? I wondered about the ‘same domain’ issue but I don’t think it’s that.

David, I can’t say for sure what your problem is without seeing an example. Can you send a demo?

But based on your description, it doesn’t sound like a problem with the menus, but something with the way the site is programmed. It could be something to do with the hash value changing in the URL, but again, I’d have to see an example, otherwise, I can only guess.

Thanks for the very prompt reply. I’ll check with my colleagues about setting up a demo on Monday and will be in touch.

We did make some minor changes in your code to prevent the ‘#’ value being shown in the URL (so the user is unaware of any change to the URL) and that works in the ‘US’ version. Could that be the issue on the ‘gb’ version?

We’re trying an alternative approach. Our Zend index.php was using Zend_Router_Route_Regex to allocate the user request to the correct controller (of which there are loads). We feel that this has become too cumbersome so we’re implementing a better MVC methodology (still Zend) now and testing it with your code.

It’s still a bit hit and miss but when (not if) we get it working, we’ll let you know.

It looks like the base URI is causing an issue in the javascript. In the case of our front page, the base URI is http://www.example.com. At the next level, it’s http://www.example.com/corporate and the JS looks for the code to run in that directory, not the top level (so, it’s looking in example/corporate for a folder called dropdown instead of looking for it in example/).

We tried setting base ref in the pages but that just gives us a base URI on our second level of example/corporate/example/corporate which is even worse!

The problem was the context at the time of the dd.load() call. And the solution was blindingly simple. We just put a “../” + in front of the “dir” and it solved the problem!

We could read baseURI and work out how many “../”‘s we need but since we know how many levels down our system will go with its URL’s, we’ll probably just stick “../../../../” into the dd.load() and the system will work.

Hey, Claude. Sorry about that, I forgot that I didn’t answer your question. For some reason I remembered answering it and thought you may have contacted me via email or something. (I get too much email!)

So, basically, I’m not entirely sure what you are trying to accomplish. From my understanding, you just want the content to push the container to hold everything, or else to scroll the container. That should not require any extra script at all, you should just be able to add “overflow: auto” to the containing element, and that should do it.

The best way for me to answer such a question would be if you put up a demo page and explained it using the page, or even right on the page. Then I can fiddle with it myself and fix it so it works for you.

Yeah, it should work fine in Chrome. The only thing I can think of is that you’re on the Chrome Dev build, which has had some issues. If you are, try it in Chrome Canary or Chrome stable, which should be fine.

You need to edit “general.js”. There, you can modify the main settings and specify the directory where your menu files are. In your case : change it to wp-content/themes/{themename}. Hope it will be helpful.

Hi, is it possible to do the effect every time i press the button, instead of doing “refresh” i would like to have a “closing” panel, than opening it again on different links… Is it possible to do? Thanks in advance!

You’d have to alter the menus slightly. First, you’d disable the part of the JS that loads the files via Ajax (that’s the part that starts with “dd.load”. Then you’d have to take the separate files and put them into the HTML, one after the other. Then, you’d have to write a script to replace the Ajax part so it will “show” or “hide” the chosen menu.

I suppose I could create an alternate version that does that, but this one was mainly supposed to be used with Ajax.

I am having the same problems that Modjtabai was having in Nov ’10 but there is no solution to his problem posted.

The menu was working fine up until I integrated it into my WordPress theme, now – after fixing an “uncaught TypeError: Property ‘$’ of object [object Window] is not a function” error (changing any reference from ‘$’ to ‘jQuery’ in the .js seems to fix it) – it is now sliding open, shows the loading graphic but then the “dropdown” div is blank/empty except for the close button.

I am using the first version of the code (ver2 completely broke the menu) and have set the variable “ext” to “.php” instead of “.html”, the menus are named the same as the files, and I think I have correctly set up the variable “dir”.

I’m not to hot on php and have been stabbing wildly in the dark at the code for a couple of hours to no avail.

Hi tony. Just looking quickly at the code, it seems that you don’t have the correct files in the directory. All the links need to point to actual files in the “dir” folder, defined in the JS variables at the top of general.js.

For example, these links should all point to the files you want to include in the menus:

I’m trying to remember how Ajax files like that work with PHP… I believe if you include a file like that dynamically, it has to be self-reliant. That is, it can’t rely on WordPress stuff that goes on in the main document.

So I think when you use PHP code, you’re causing an Apache error, because it doesn’t know what the function “wp_nav_menu” is. I could be wrong, but that might be the problem.

Can you try putting some non-dependent PHP in there, like a simple echo statement only, to see if that breaks it? It shouldn’t.

If you do think that I will not be able to use wp_nav_menu() function then it doesn’t look like I can use this solution as the menus will need to be editable through WordPress. Shame, I liked the tab switcher element once one menu was opened.

This causes an “internal server error’. Something’s going on on your server that’s causing PHP files to not work in that directory. You might have to check with your host or something.

Thinking about it now, it should work and even the WP functions should work just fine. It has to be something on your server that’s causing the problem, since that page won’t even load outside of the menus.

It should work. Just make sure that the image reference is using the proper path. I believe the path needs to be relative to the HTML document, not relative to the JS. Try using an absolute path like this:

<img src=’http://whatever.com/images/source.png’>

and see if that helps. In the meantime, if I get a chance, I’ll test it myself and post an answer back here.

I thank you for your menu, I look for it for a long time. I have nevertheless a problem, I wish(desire) on the place(square) of links into the trap sliding to post(show) a complete page there containing forms of the type(chap) contact for example. Yet(now), only the links display.

What I would want to make is he(it) possible ?
How may I make him(it) ?

I thank you for your help(assistant).

(France)

( This message in summer writes in French then translates into Englishman(English people), I am sorry I do not speak English)

I don’t think this menu can do what you want. I’m not sure I fully understand, but you cannot put a full page to display inside the menu. It sounds like an odd request, but if that’s what you’re saying, then no, you cannot display a full contact page inside the menu panel.

If you mean that you want the links to lead to another page, well, you’re going to have to go through the JavaScript and find a way to reverse the fact that all the links are disabled by default. The links only trigger via JS, they will not link to their HREF value.

Hello I currently am developing and branding Sharepoint 2013 sites. I’ve used this plugin to add a mega drop down nav on a sharepoint site. Now the issues at hand is that when viewing the sharepoint 2013 site in IE8 the dropdown content does not show up. It shows up in other browsers and even IE9 but not IE8.

It’s using Ajax to pull in the menus, so if I’m not mistaken, you have to be running a local web server to get it to work. Personally, I have Apache/PHP/MySQL installed locally and I use a program called XAMPP to manage those.

I don’t think it will work without a real server, because of the Ajax interaction.

That’s a bit of a tough one. You’ll have to identify which menu is being clicked, then respond accordingly in the JavaScript. Right now, the code isn’t really set up to run that way, so it’s not easy. Basically, I’d have to restructure the code to be a little more modular/functional, but I don’t have the time right now.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.