[End of Demo Page]

jqDock ... a jQuery plugin

DOCTYPE : XHTML 1.0 Transitional

Transform a set of images into a Mac-like Dock menu,
horizontal or vertical, with icons that expand on rollover!
(Minimum requirement : jQuery v1.2.3)

jqDock

A jQuery Plugin

The Dock - as anyone familiar with a Mac will know - is a set of iconic images that expand when rolled over with the cursor, and usually perform some action when clicked. This plugin mimics that behaviour by transforming a contiguous set of HTML images into an expanding Dock, vertical or horizontal, with or without labels.

Example of a vertical Dock Example of a horizontal Dock

Basically, all the Dock does is expand a reduced size image towards its full size when the cursor is on or near it. You can specify a vertical or horizontal orientation for the Dock, and select the direction in which the image should expand and whether to show labels or not. The styling and positioning of the Dock is (almost) entirely down to you.

You can use 2 different images for clarity, one for the minimised 'at rest' state, and one for performing the enlargement to its full size. Alternatively, you can just use the one larger image as long as you are happy with its definition when reduced by the browser.

There is no restriction on the type of image that can be used, but obviously if you are applying any styling to your Dock that makes it stand out against the background (such as a border or background colour), then a transparent GIF or PNG8 (an IE6 limitation) may be preferable to an image that displays with an opaque background. The images can be enclosed within links, or not, depending on how you wish to control your navigation or application. The only requirement is that the parent container, probably a DIV, holds only images and/or anchors that enclose an image.

You may need to ensure that the placement of your menu allows for expansion, either horizontally or vertically depending on the assigned alignment. The Dock will extend both ends of its major axis as the images are rolled over, as well as enlarging the relevant images themselves, and you want to avoid having it disappear off screen, or under other elements, if you can help it. The Dock will always do its very best to position itself centrally (along its major axis) within what it thinks is the maximum space required for any expansion. However there are times - such as when applying extra padding as spacing between images - when this might not be accurately calculable and may require positional tweaks to keep the Dock in view.

The Dock uses all the document's original HTML, in other words it does not create clones and append them to the end of the document. This means that the container element to which you apply jqDock() is what controls the position of the Dock, and what elements the Dock can appear on top of. Although absolute positioning is used, and a few wrapper elements are added below the container element, any elements that come later in the document than the container element have the opportunity of obscuring all or part of the Dock. It is therefore recommended that the container element be placed or positioned with care within your document such that the Dock will not appear underneath any other elements on the page.

Change Log

  • v1.2
    • adding handling of Opera 9.5
    • updated demo to use jQuery v1.2.6
  • v1.1
    • some speed optimisation within the functions called by the event handler
    • added positioning of labels (top/middle/bottom and left/center/right)
    • added click handler to label (triggers click event on related image)
    • added jqDockLabel(Link|Image) class to label, depending on type of current image
    • updated demo and documentation for label positioning and clicking on labels

Credits

jqDock was inspired by, and owes full credit to, Isaac Rocca's "iconDock" plugin - http://icon.cat/software/iconDock/. I have simply re-modelled it, tweaked it, expanded it, and re-packaged it.

HTML

Example:
<div id='menu'>
  <img src='image1.gif' alt='image1.png' title='' />
  ...
  <a href='page.html' title=''>
    <img src='imageN.png' alt='' title='' /></a>
  ...
</div>

A menu contains images, which may or may not be within links - you can mix and match as you wish. You should provide css styling as necessary to position your menu where you want the Dock to appear. You can hide it if you wish (display:none;), and you can set the width and/or height styles on the images, but you should avoid using the width and height IMG attributes.

If the 'alt' attribute contains what looks like an image path (ends with a dot-suffix of gif, png or, jp[e]g) then 'src' will be used as the small image and 'alt' as the larger, expanding one.

Images are always expanded to their full natural width/height, or a fraction thereof, depending on the position of the cursor at the time. You can not control the ultimate dimensions of the expanding image by css, because jqDock overrides it, and if you try using the width/height attributes things won't work as expected.

By default the 'labels' option is off, and jqDock will remove any values for 'title' and 'alt' attributes (after examination), in an attempt to prevent the browser displaying a tooltip when hovering over an image (causes 'fluttering' in some browsers if the cursor is allowed to move over the tooltip). Also, jqDock will remove all text nodes within the menu - this helps to ensure a known and standard presentation of the Dock, and smooth animation.

jQuery

Important! This plugin requires at least jQuery v1.2.3, because it uses API constructs that only became available in that version.

Link in the jqDock source (full or compressed) after jQuery itself...

Example:
<script type='text/javascript' src='jquery-1.2.3.min.js'></script>
<script type='text/javascript' src='jquery.jqDock.js'></script>

To convert your HTML into a Dock, simply call the jqDock function in the standard manner...

Example:
jQuery(document).ready(function(){
  jQuery('#menu').jqDock(options);
});

jqDock() supports full chaining, and noConflict().

Options

There are a number of options available, which can be set on per-Dock basis. None of the options are mandatory since they all have defaults.

Example:
var opts =
  // horizontal Dock with images expanding downwards in the vertical axis...
{ align: 'top'
  // set the maximum minor axis (vertical) image dimension to 48px
, size: 48
  // add labels..
, labels: true
  // swap the GIF extension for PNG extension for the larger image...
, source: function(i){ return this.src.replace(/gif$/,'png'); }
};
$(this).jqDock(opts);
  • align : string, default = 'bottom', values = 'top', 'middle', 'bottom', left', center', 'right'
    Fixes the horizontal/vertical main axis, and direction of expansion. A value of 'top', 'middle' or 'bottom' produces a horizontal Dock with, for example, 'bottom' fixing the bottom edge of the images in place such that they only expand upwards in the minor (vertical) axis. Likewise, values of 'left', 'center' or 'right' provide a Dock with a vertical main axis, with images expanding from the left edge, from the centre, or from the right edge respectively.
  • coefficient : number, default = 1.5
    Attenuation coefficient. This controls the relationship between the distance from the cursor and the amount of expansion of any affected image within that distance. A coefficient of 1 makes the expansion linear with respect to distance from cursor; a larger coefficient gives a greater degree of expansion the closer to the cursor the affected image is (within distance).
  • distance : integer, default = 54 [px]
    Attenuation distance from cursor, ie the distance (in pixels) from the cursor that an image has to be within in order to have any expansion applied.

    Note that attenuation is always calculated as if the Dock was 'at rest' (no images expanded), even though there may be expanded images at the time.
  • duration : integer, default = 500 [ms]
    The duration (in milliseconds) of the initial 'on-Dock' expansion, and the 'off-Dock' shrinkage.
  • labels : boolean or string, default = false, values = true, 'tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'
    This enables/disables display of a label on the current image.
    Allowed string values are 2 characters in length: the first character indicates horizontal position (t=top, m=middle, b=bottom) and the second indicates vertical position (l=left, c=center, r=right). So 'br' means bottom-right! In the case of either middle or center the position is calculated with respect to the center of the actual image (any extra padding applied by css styling is ignored); the other settings all take into account any extra padding.
    If simply set to true, jqDock will use its default positioning for the label, which for 'left' and 'right' alignment is the top opposite corner to the fixed edge (ie. for alignment 'left', the default is 'tr', top-right); for any other alignment, the default is 'tc' (top-center).
    To determine the text for the label, jqDock looks firstly for text in the image's 'title' attribute; if not found, it will then look for text in the 'title' attribute of the parent link - if there is one - and use that if found.

    Please be aware that enabling this option will have a slight effect on the performance of the Dock, simply due to the additional processing required to position the label correctly.
  • loader : string, default = null, values = 'image', 'jquery'
    This overrides the default image loader used by jqDock. Depending on the browser, jqDock uses an image loader based on either "new Image()", or the jQuery HTML constructor "jQuery('<img />')...". If your Dock is not being displayed, and you have triple checked all your image paths, try setting this option to 'image' or 'jquery' to override the default loader.
  • size : integer, default = 36 [px]
    This is the maximum value of the minor axis dimension for the shrunken images. For example, an image of natural dimensions 90x120 (width x height), placed in a horizontal Dock (say, 'align' = 'bottom') would, by default, be sized down to 27x36. This is because height is the minor axis in a horizontal Dock, and to keep the presentation of the 'at rest' images neat and tidy it is the height that is governed by the size option. Conversely, in a vertical Dock it would be the width that was capped at the size value, with height being set proportionately.
  • source : function, default = false
    Function for providing an alternate large image source path. For instances where you are either unable, or do not want to put the large image's path in the IMG's 'alt' attribute, but you still want to have a small and large image for clarity, this function may be useful.

    If provided, it is called once per image during setup, and is given the context of the image element and passed the index of the image within the current Dock; it is expected to return a valid image path, or false/null to continue using the defaults ('alt' or 'src'). (See example above)

HTML Transform

The HTML transform varies slightly depending on the vertical/horizontal orientation of the Dock. There are also inline styles (not show below) included on the additional elements which can vary depending on the browser in use at the time. As an example...

Grey : Original HTML
Blue : Added by jqDock()
Purple : Added by jqDock(), vertical Docks only
Green : Added by jqDock(), only if 'labels' option has been enabled
Red : Removed by jqDock()
<div id='menu'>
  <div>
    <div class='jqDock'>
      <div>
        <img src='image1.gif' alt='image1.png' title='' class='jqDockMouse0_0' />
      </div>
        ...
      <div>
        <a href='page.html' title=''>
          <img src='imageN.png' alt='' title='' class='jqDockMouse0_n' /></a>
      </div>
        ...
    </div>
    <div class='jqDockLabel jqDockMouse0_00 jqDockLabel(Link|Image)'>
      Label Text
    </div>
  </div>
</div>

CSS Styling

Using the jqDock and jqDockLabel classes, you can apply CSS styles to modify the presentation of the Dock and labels (if enabled). For examples, I suggest looking at the later part of the style.css stylesheet used by these pages (Example CSS) - it is fully commented and, given the number of demo Docks, should provide all the hints you need.

The jqDockMouseX_Y classes are used internally by the mouse events handler to determine the Dock (X) and the image (Y) being targeted, with a special double-zero ('_00') suffix for the Dock's label.

The Dock's label has an additional class - jqDockLabelLink or jqDockLabelImage - which indicates whether the current image is an image within a link, or just an image, respectively. You can use this class to, for example, set the cursor for the label to be the same as the image beneath it.

Tested Browsers

I have tested this demo page, in each of its DOCTYPE (or not) incarnations, in the following browsers/operating systems:

  • IE6 (Win XP)
  • IE7 (Win XP)
  • Firefox 2.0.0.11 (Mac)
  • Firefox 2.0.0.12 (Linux)
  • Firefox 2.0.0.13 (Win XP)
  • Opera 9.24 (Mac)
  • Opera 9.26 (Win XP)
  • Opera 9.5 (Win XP) - as of v1.2
  • Safari 3.1 (Mac & WinXP)

If anyone can confirm that jqDock works - or doesn't! - in other browsers and/or operating systems, please let me know.

Other Questions

  1. What files do I need in order to run jqDock?
    • Just the script file - jquery.jqDock.js or jquery.jqDock.min.js (compressed version).
  2. Why isn't the Dock being displayed?
    • Check that all your image paths are correct, because if jqDock fails to load any image the Dock will not be shown.
    • See if the Dock diplays correctly in another browser - there is always the possibility that jqDock doesn't work for your browser/operating system combination.
    • Try changing the image loader (options.loader = 'image' or 'jquery'). jqDock uses 2 types of image loader, and it could be that the default for your browser is incorrect.
    • Check for any elements other than images or link-wrapped images (IMG or A>IMG) in the menu that you are attempting to turn into a Dock.
  3. Why is nothing happening when I move my mouse over the images?
    • Check that jqDock() is being called after the document has loaded. (Ref. the jQuery tutorial : Launching Code on Document Ready).
    • Check that some other element of your page is not obscuring the Dock, and thereby intercepting the events (unlikely, yet possible!).
  4. Why is the text of my links not being displayed?
    • jqDock removes all text nodes within the scope of the menu element, including link text. Not doing so would cause variations in the presentation of the Dock between browsers and DOCTYPE'd pages; it would also make the width/height calculations almost impossible.
  5. Why am I not seeing labels on the Dock images?
    • The labels option is off by default.
    • Labels only appear on expanded images, and then only on the image currently beneath the cursor.
    • The text for a label is taken firstly from the title attribute of the menu image; if that is not available, and the image is wrapped in a link, then the title attribute of the link will be used. If neither of these are available, then no label will be displayed.
  6. Can I change the position of the label?
    • As of v1.1, yes (see Options).
    • The positions can be 'tweaked' by css styling of div.jqDockLabel, eg. adding padding to the label (see the Example CSS).
  7. How do I change the style of the labels?
    • Add a CSS style for div.jqDockLabel, setting font, color, etc, as required. See the examples at the bottom of Example CSS.
  8. How do I stop the image expansion being 'jerky'?
    • There is actually very little you can do. Different browsers, different operating systems, and different machines, all make for a varied experience (I found Safari 3.1 on Win XP to be very jerky compared to the Mac version - but no surprise there really). I have reduced the processing overhead in the events handler as much as possible, and about the only thing you can try is turning off labels (if they are enabled), and possibly reducing the distance option (the fewer images that are in an expansion state at any time, the less the processing involved). Sorry.
  9. Why can't I use an earlier version of jQuery than v1.2.3?
    • The jqDock plugin utilises some of the optimised API features of v1.2.3 in order to keep the codebase footprint as low as possible without compromising readability. Also, from a purely selfish point of view, it is easier to pick the current (at the time) version and test it, than it is to use an earlier version and have to test all subsequent versions as well.
  10. Why is the Dock disappearing under other element(s) on the page?
    • Because the target menu element (and its surrounding elements?) have not been correctly positioned in order to avoid just such a situation.
    • jqDock does not rearrange the page's original HTML, it merely enhances it with a few insertions within the target menu element's scope. The position of the Dock is totally dependent on the styling applied to the target menu element, plus any additional styling you apply to div.jqDock.
    • Absolute positioning is limited to the immediately containing element, so because jqDock does not move the target menu elements to the end of the body element, it is impossible for jqDock itself to ensure that the Dock will be fully visible.
  11. How do I change the appearance of the Dock?
    • Apply css styling to the div.jqDock that is inserted within the target menu element's scope. See the examples in the Example CSS.
  12. Can I dynamically add/remove images on an existing Dock?
    • Yes, of course, with jQuery you can do almost anything you like ... but you'll corrupt the Dock's layout and positioning.
  13. Can I disable elements of the Dock?
    • You can enable/disable clicks in the same manner that you would any other element.
    • jqDock does not control what happens when/if an element is clicked - you do. If your menu has any pure images (not wrapped in links) then you will have to bind any required click events to them. If there are linked images in the Dock then what happens when the link (the image) is clicked is down to you.
  14. Why do I need a large and a small image?
    • You don't, you can just use the larger image. However, some images do not retain good clarity when reduced by a browser, so you therefore have the option of providing a more defined small image for when it is not being expanded.
  15. Can I remove jqDock from a menu element?
    • No, sorry, there is no 'un-jqDock' facility.
  16. Can a Dock be given a 'fixed' position?
    • I don't know, it's not something I have tried. Bear in mind, though, that IE6 (and IE7, quirks mode) can't cope with fixed position per se, and it has to be simulated.
  17. Why does nothing happen when I click on a label?
    • If the related image is contained within a link, and has no click handler of its own, then the link will not be activated. You will need to provide some sort of click handler on the image - see the script on the demo page(s) for an example.
    • When a label is clicked, jqDock triggers the 'click' event for the image. However, the native action for a link can not be activated from other elements/events, hence the need for a click handler.