Advanced docking using jQuery

Some time ago I was doing some proof of concept: how Visual Studio docking functionality can be done with jQuery and unordered lists. Basically, the main goal was to implement multiple docking and undocking functionality. This tutorial will show you the results of PoC.

Download the example View live demo

The requirements

This is how docking should behave:

  1. When user hovers an item on vertical menu, its submenu should slide in from left to right (points 1 and 2 in the image below) and overlay the content
  2. When user move the mouse pointer outside the panel it should slide back
  3. If user clicks on "Dock" link (point 3 in the image below), panel should fix in the current position while content moves to the right of the panel in order to be seen
  4. If users "undock" the panel it should slide back
This way users can chose whether they want to perform an action and continue with work or they want to have available actions permanently visible.

But that is not all. I wanted multiple panes to be able to dock in the same time. If one panel only is docked it should be 100% height. With each new panel docked, height should be recalculated so that all panels have the same height value (like in the image below). If there are docked panels and user wants to slide in another panel temporarily, it should overlay docked panels.

 

A "brief" explanation

The idea was to have a navigation based on nested ULs. This is nothing new, but I wanted to create more than just CSS&UL based menus that can be used as toolboxes or action links as well. So the structure is very simple. The main UL with id="dock" will act as a vertical navigation bar that contains three links (in this example). Each link will have a nested UL that will represent a docking panel with some sample list items. Each first listitem will act as a header for docking panel, containing panel title and Dock/Undock exclusive links.

<ul id="dock">
    <li id="links">
        <ul class="free">
            <li class="header">
                <a href="#" class="dock">Dock</a>
                <a href="#" class="undock">Undock</a>Links
            </li>
            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>

            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>
        </ul>
    </li>
    <li id="files">
        <ul class="free">
            <li class="header">
                <a href="#" class="dock">Dock</a>
                <a href="#" class="undock">Undock</a>Files
            </li>
            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>
            <li><a href="#">This is one item</a></li>

            <li><a href="#">This is one item</a></li>
        </ul>
    </li>
    <!-- more submenus here -->
</ul>
<div id="content">
    <!-- content here -->
</div>

Let's see how CSS can help use to style this lists.

body{margin:0px; font-family:Arial, Sans-Serif; font-size:13px;}
/* dock */
#dock{margin:0px; padding:0px; list-style:none; position:fixed; top:0px; height:100%; z-index:100; background-color:#f0f0f0}
#dock > li {width:40px; height:120px; margin: 0 0 1px 0; background-color:#dcdcdc; background-repeat:no-repeat; background-position:left center;}
#dock #links {background-image:url(links.png);}
#dock #files {background-image:url(files.png);}
#dock #tools {background-image:url(tools.png);}
#dock > li:hover {background-position:-40px 0px;}
#content {margin: 10px 0 0 60px;}

The main #dock UL has fixed position in the top left corner of the window in order to be visible after scrolling. Each listitem in #dock unordered list presents one vertical link which hovering causes its child list (or simply - docking panel) to slide-in. I used CSS sprites to show hover states for each LI.

body{margin:0px; font-family:Arial, Sans-Serif; font-size:13px;}
/* dock */
#dock{margin:0px; padding:0px; list-style:none; position:fixed; top:0px; height:100%;
    z-index:100; background-color:#f0f0f0; left:0px;}
#dock > li {width:40px; height:120px; margin: 0 0 1px 0; background-color:#dcdcdc;
    background-repeat:no-repeat; background-position:left center;}
#dock #links {background-image:url(links.png);}
#dock #files {background-image:url(files.png);}
#dock #tools {background-image:url(tools.png);}
#dock > li:hover {background-position:-40px 0px;}

Also, we need to style docking panels. First three lines in this CSS script define styles of listitems on docking panel in normal and hover state. Fourth line sets visibility of nested UL's while hovering its parent LI's. Next line defines the docking panel itself. Each panel is positioned absolutely, and initially will be hidden (left: -180). Also each one of them will have z-index:-1 in order to be shown above docked UL's that have z-index:-2.

So far, so good. If wanted to create a simple CSS based navigation I could have done it with CSS only. But I want the panels to slide-in and slide-out on hover.

$("#dock li ul").height($(window).height());
$("#dock li").hover(function(){
    $(this).find("ul").animate({left:"40px"}, 200);
}, function(){
    $(this).find("ul.free").animate({left:"-180px"}, 200);
});

This jQuery scripts does exactly what I want. Te first line sets the height for each panel to be the same as window height. Now we have menus that work.

Docking/undocking functionality

Now when menu works, I can add docking functionality. The goal is to be able to dock as many panels as I want, and they all should be visible one below each other. To achieve this I need to count how many panels are docked and to recalculate their heights to fit inside the window. When panel is docked, its "free" CSS class will be replaced with "docked" class in order to have a clear distinction between docked and undocked items and to ease the manipulation.

The code below then recalculates heights for each docked panel and hides "dock" link and shows "undock" link. It will also check for number of docked items in order to move content to the right if at least one panel is docked.

$(document).ready(function(){
    var docked = 0;
    
    $("#dock li ul").height($(window).height());
            
    $("#dock .dock").click(function(){
        $(this).parent().parent().addClass("docked").removeClass("free");
        
        docked += 1;
        var dockH = ($(window).height()) / docked
        var dockT = 0;               
        
        $("#dock li ul.docked").each(function(){
            $(this).height(dockH).css("top", dockT + "px");
            dockT += dockH;
        });
        $(this).parent().find(".undock").show();
        $(this).hide();
        
        if (docked > 0)
            $("#content").css("margin-left","250px");
        else
            $("#content").css("margin-left", "60px");
    });
});

Undocking functionality is very similar. It actually do an opposite actions in comparing to docking functionality :)

     $("#dock .undock").click(function(){
        $(this).parent().parent().addClass("free").removeClass("docked")
            .animate({left:"-180px"}, 200).height($(window).height()).css("top", "0px");
        
        docked = docked - 1;
        var dockH = ($(window).height()) / docked
        var dockT = 0;              
       
        $("#dock li ul.docked").each(function(){
            $(this).height(dockH).css("top", dockT + "px");
            dockT += dockH;
        });
        $(this).parent().find(".dock").show();
        $(this).hide();
       
        if (docked > 0)
            $("#content").css("margin-left", "250px");
        else
            $("#content").css("margin-left", "60px");
    }); 

It can be optimized and polished or even used to create a plugin, but that will have to wait for a while. I hope you will make some use of this.

More articles in Blog archive or elsewhere
Advertisement

56 Comment(s)

Gaya

Gaya 01 Jun 2009 #

This looks really cool, Janko! This gives a nice user experience. Might be good for CMSes! Good job dude!

Neil

Neil 01 Jun 2009 #

Very Nice....would be perfect for an admin console

Simon

Simon 01 Jun 2009 #

Very nice ! Good work !
As already said, this could be perfect for an admin console.

Anthony Grace

Anthony Grace 01 Jun 2009 #

Very nice work and extremely useful! Smile

Soh

Soh 01 Jun 2009 #

Sweet, thanks for this tut!

Ben Tremblay

Ben Tremblay 01 Jun 2009 #

Sweet.

Do you ever use <a href="www.netvibes.com/">NetVibes</a>? Not saying that's the design I'm looking to achieve, but that's the sort of functionality I need. This here is definitely a step in that direction.

p.s. Name and EMail in your comment form are white text / white background. The country drop-down too. (FF2)

Nicolas Pascual

Nicolas Pascual 01 Jun 2009 #

Great tutorial Janko! Like always you do!

Kawsar Ali

Kawsar Ali 01 Jun 2009 #

Really cool tutorial. This could be useful.

Allan

Allan 02 Jun 2009 #

This is good and all, but as Jacob Nielsen points out in his recent article about mega-menu's ( www.useit.com/alertbox/mega-dropdown-menus.html ) adding a .5 second delay to the hover increases usability (according to their studies). Using the jQuery HoverIntent plug in makes this easy: cherne.net/brian/resources/jquery.hoverIntent.html

I'll be subscribing to your feed. Thanks for publishing!

Mina Saad

Mina Saad 02 Jun 2009 #

Wowwwwwwwwwwwwwww great

Farooq

Farooq 02 Jun 2009 #

really nice and good tutorial and jquery plugin

Janko

Janko 02 Jun 2009 #

Thanks everyone!

Ben: I don't use NetVibes but their UI is interesting Smile I checked in FF2 and it works fine. Do you use any toolbar? Some readers reported similar issues with Google toolbar.

Allan: Good point about delay. Thanks!

Davide Espertini

Davide Espertini 02 Jun 2009 #

Great! Nice tutorial!

jpablobr

jpablobr 02 Jun 2009 #

Excellent, thank you!

Marko

Marko 02 Jun 2009 #

Great article as always! Bookmarked ;)

Tom

Tom 02 Jun 2009 #

Wow.

The things people do with jQuery continues to amaze me.

Muhammad Mosa

Muhammad Mosa 02 Jun 2009 #

Mate, this is a killer post. have you considered making this as plugin or widget?!
It would be great if you do it

Viking Beard

Viking Beard 02 Jun 2009 #

Unbelievable tutorial...this same functionality written in .net would be hundreds of lines of code. Thank you thank you thank you thank you!

Janko

Janko 02 Jun 2009 #

Thanks guys!!!

Muhammad: Yep, I think plugin will come out at the end. There are some things to consider in order to make it pluggable everywhere.

Ruud

Ruud 03 Jun 2009 #

awesome post Janko, thank you!

Amr Elsehemy

Amr Elsehemy 03 Jun 2009 #

Nicely written, excellent job and very nice demo.

Russ

Russ 03 Jun 2009 #

This is a very nice bit of code.  I would suggest a little addition to capture the onResize event and adjust things when the vertical  / height of the page changes.

JQ

JQ 03 Jun 2009 #

Great idea.  I could see this being used for many for many different sites.  It would really depend on the context of the site that's using it.  There are pros and cons to implement something like this.

Here are a few off the top of my head.

Pros:

- It is an amazing idea for site with a large navigation system
- Combined with animation it's adds a stickiness and a unique experience
- Users will love the ability to 'customize' the navigation

Cons:

- Usability the dock / undock states are not maintained on page refresh
- The moving menus may disrupt the natural flow of the site
- It might pose a problem to the organic traffic / SEO strategies

Again it all really depends on the context of the site will determine if this functionality will be a benefit.

Great work dude.

jzigbe

jzigbe 04 Jun 2009 #

Very Nice! Thanks

Abdel

Abdel 04 Jun 2009 #

Really good tutorial.. Thanks!

Nathan

Nathan 05 Jun 2009 #

Doesn't work on Chromium though Smile

Janko

Janko 05 Jun 2009 #

Thanks everyone for comments!

Russ: That is one of the thing's I'll definitively add!

JQ: I agree, this one really depends on the context. I believe that it can be more useful in web applications and admin sites as a toolbox, than navigation on public website.

Nathan: It's important to work in Chrome Laughing

Dave D

Dave D 05 Jun 2009 #

Thanks! detailed and useful. By looking at the title, I thought it is about a mac-like dock. If anyone is interested - there's a cool example on coderun.com
Really impressed by what you've done with jQuery.

Liu Hao

Liu Hao 08 Jun 2009 #

Thanks.really cool~

dalton

dalton 08 Jun 2009 #

Cool.  I would be interested to see how you would go about docking it to the right side of the screen, taking the scrollbar into account.

Carlo

Carlo 08 Jun 2009 #

A wordpress plugin???
Can you create it?

Janko

Janko 09 Jun 2009 #

dalton: I guess the issue will be docked panels. In that case, only the main content should be scrollable not the entire page. That's how it's work in Visual Studio at least.

Tommaso Baldovino

Tommaso Baldovino 10 Jun 2009 #

It would be good to have an accessible version of this script: side menus should be visible even with no JavaScript enabled. You've done a good job indeed ;)

Alidad

Alidad 13 Jun 2009 #

this is nice, I want to use that for my site but i was wondering how can i change to the right side instead of left side!

Alidad

yosry

yosry 04 Jul 2009 #

Very nice work  i love it  but not working on IE6 Frown

the website guy

the website guy 10 Jul 2009 #

I like the concept... the only thing that I don't like is the way that it instantly disappears when you hover away.  I like how it slides in - it would be better if it slid out as well. - Just my opinion

TheWaffleSupremacy

TheWaffleSupremacy 14 Jul 2009 #

It's awesome!  Very cool what you've done!

But I have to say, just for amusement, look at it on a mobile browser. I know, not what it's intended for, but it still gave me a chuckle. ;)

Gadget

Gadget 15 Jul 2009 #

Looks like I done everything like in the example. But I still have some problems..

Mohammad Saad

Mohammad Saad 25 Jul 2009 #

it does not work in IE 6... any solution??

swaino

swaino 25 Jul 2009 #

Hi,
Love the plugin, but I was wondering is there something written in JQuery that works like the (dare I say!) Coolite/ExtJS window docking system.  I love the way you can add N,E,S,West panes and have everything dock...

Firebubble Design

Firebubble Design 28 Jul 2009 #

Great tutorial, i could see this being very useful for future sites with large navigations, thanks for the post.

SJL Web Design

SJL Web Design 29 Jul 2009 #

This would be perfect for an admin area of a CMS, thanks for sharing it.

aki

aki 12 Aug 2009 #

Awesome, my clients are very happy with this feature. Thanks!

Web Designer

Web Designer 18 Sep 2009 #

Hey Janko,
Thanks a lot for the tutorial. Very nice effect but difficult to implement as well. I would probably go for a CSS solution in this specific case.

Daniel Gibbs

Daniel Gibbs 21 Sep 2009 #

Changing it from left to right? Just take a look at the code and reverse everything from left to right, it's really straight forward (in response to a question above).

Anyway, great post and a very logical approach. Cheers

Alex Similou

Alex Similou 30 Sep 2009 #

Guys,
Do you have any idea of how I can make the script 'remember' the last state (docked/undocked) of the tabs? After refreshing the page the docked tabs go back to the 'undocked' state.

Richard Sharpe

Richard Sharpe 02 Oct 2009 #

@ Mohammad Saad

Most things dont work in ie6, can I suggest don't use ie6 ?

How I wish the world was that simple a place Smile

Matt  Gregory

Matt Gregory 12 Oct 2009 #

DO people really still use ie6 anymore?

Max

Max 25 Oct 2009 #

Awesome explanation. I'm only coming to grips with jQuery slowly but this post has helped me move a little closer to understanding the subtleties involved.

Michelangelo

Michelangelo 26 Oct 2009 #

Hi,

Fantastic solution! How can I set one of these 3 panels as docked instead of UnDocked at the end of the loading of the page?

thanks

dise&#241;o web

diseño web 27 Oct 2009 #

very good!! excellent menu! really very professional

Trent - Work at Home

Trent - Work at Home 09 Nov 2009 #

I agree with the comment above in that I didn't think anyone used IE6 anymore. Anyway, great post. I appreciate it! Thanks.

klaus

klaus 19 Nov 2009 #

i am so happy that i found this site. iquery rocks. i still learn the demo stuff on http://docs.jquery.com/Tutorials but yours are great.

Ham

Ham 19 Nov 2009 #

How can I make one of the items dock by default when the user loads the page?  Appreciate your help.

Dave

Dave 27 Jan 2010 #

I think a nice addition to this, if you could implement it, would be to have each of the main headings clickable to expand / contract it's child elements similar to an accordion style menu

Formulis Web Design

Formulis Web Design 15 Feb 2010 #

Janko, that is a very cool menu system! I could see that being extremely useful in software user guides, or just about anything with complex nesting of information. Thanks!

Comments are closed
via Ad Packs
9292