Roundabout for jQuery

v1.1 by Fred LeBlanc

Move Elements with Style

  • :)
  • :D
  • :p
  • :*
  • :B
Try it! Click on a box in the back.
 

Roundabout is a jQuery plugin that converts a structure of static HTML elements into a highly customizable turntable-like interactive area. (And now, not just turntables, but many shapes!)

In its simplest configuration, Roundabout works with ordered- and unordered-lists, however after some quick configuration, Roundabout can work with an set of nested elements.

Oh, and Roundabout is released under the BSD license. If you’re not sure what that is, you can find the entire license in the source code. Go nuts, I encourage it.

Update, March 13: Introducing Roundabout v1.1! What’s new:

You should be able to drop v1.1 in right on top of v1.0 and all should work. I’ve done my best to bug-check this release, but if you find anything, please let me know! I’ll get on it ASAP.

Requirements & Add-Ons

Requires jQuery 1.2.3+, 1.3.x or 1.4.x and has been built to play nicely with the following plugins:

Mind-Blowing Demonstrations

Here are just a couple of ways that Roundabouts can be configured.

More demonstrations by popular demand:

Roundabouts in the Wild

Here are a couple of places out on the web that are using Roundabout:

http://jquery.org/

The jQuery Project manages all of the jQuery projects, including jQuery Core, jQuery UI, Sizzle and QUnit.

Let’s have a round of applause for Fred’s Roundabout plugin for jQuery, it feels good to use… so many options!

— Boaz Sender
http://vtm.be/

VTM is a popular TV station in Belgium.

I’m really happy with your plugin, nobody seemed notice the change from the original Flash to your jQuery plugin. It’s actually replacing a resource-hogging Flash version. Roundabout fixes the CPU load, the HTML fits right in the CMS — no special XML needed, and as a bonus now works on iPhones!

— Thomas Decrick

Have you seen a Roundabout somewhere around the Internet? Are you using Roundabouts in your own projects? Have something awesome to say about Roundabout? Let me know!

Your Very First Roundabout

This three-step guide will assist you in converting a boring unordered-list into an exciting Roundabout! Once this tutorial is complete, check out how to customize your Roundabout. Once you’ve mastered that, learn about Advanced Techniques.

This guide assumes that you have an unordered-list in your HTML somewhere, maybe one that looks like this:

<ul id="myRoundabout">
   <li>Box 1</li>
   <li>Box 2</li>
   <li>Box 3</li>
   <li>Box 4</li>
</ul>

1. Include Your Scripts

Before we can set our Roundabouts loose, we must first include the Roundabout script on our page. Because this script believes in unobtrusive JavaScript, you can put these lines right before the </body> of your HTML document.

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.roundabout-1.0.min.js"></script>

Copy & Paste Warning!

The paths used here will only work if the HTML page is in the same directory as our scripts. This is not usually good organization, so change your paths accordingly.

2. Set Up Your CSS

Due to unordered-lists having bullets and built-in indenting by default in most browsers, we’re going to need to make some CSS changes so that these features don’t get in the way once Roundabout is up and running. Below is some sample CSS that will set up a nice, standard Roundabout.

<style type="text/css">
   /* <![CDATA[ */
   .roundabout-holder { padding: 0; height: 5em; }
   .roundabout-moveable-item {
      height: 4em;
      width: 4em;
      cursor: pointer;
      background-color: #ffc;
      border: 1px solid #999;
   }
   .roundabout-in-focus { cursor: auto; }
   /* ]]> */
</style>
By the way: Like this syntax highlighting? Use TextMate? Get the Clouds theme now!

Copy & Paste Warning!

Feel free to use this code on your site, but it’s much more important to know what classes are being applied (and when), and what they mean. It’s a 5-minute read, take the time to learn it.

3. Attach Roundabout

This can happen in a separate file (included after your jQuery and Roundabout script calls from step 1), or it can be right on the page. Let’s put it right on the page for the sake of this example.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul#myRoundabout').roundabout();
   });
   // ]]>
</script>

Copy & Paste Warning!

Make sure you change the jQuery selector to point to the right elements. If you’ve been copying and pasting this whole time you should be OK.

There are two things happening here: first, we’re using the document’s ready state to trigger our Roundabout’s loading. This is important; we don’t want Roundabout looking for an HTML element that isn’t in the DOM yet.

Second, we select all of the HTML elements that we want to turn into Roundabouts with a jQuery selector and then attach the .roundabout() method onto it.

Save your file and load it in a browser. If all of your paths are correct and the CSS is in place, you should have a Roundabout!

Roundabout CSS

There are three classes that will be applied to elements that are apart of Roundabouts. For a more unobtrusive solution, it is best practice to style using these classes rather than styling the actual HTML elements themselves. Otherwise, your anti-JavaScript users will see the styles of a Roundabout without the positioning. The results may be messy.

.roundabout-holder

This class is always added to the element(s) holding the elements that will be moving around. In default scenarios, this will be applied to the <ul> or <ol> element — whichever elements are selected by the jQuery selector onto which you attach .roundabout();.

.roundabout-moveable-item

This class is always added to all elements that will be moving around within your Roundabout. In default scenarios, this will be applied to all <li> elements that are immediate children of your <ul> or <ol> tags that have had roundabout-holder applied to them.

.roundabout-in-focus

This class is temporarily added to an element with a class of roundabout-moveable-item that is “in focus.” An element is only in focus when its position matches the focusBearing and no animations are playing within that Roundabout

Why can’t items be in focus while animations are running?

Let’s say, for example, you’ve set your .roundabout-in-focus elements to change background-color. We don’t want items flashing as they pass through the focusBearing.

Knowing this, it should follow that only one or fewer elements per Roundabout will ever have this class applied to it at any one time.

Customize Your Roundabout

Now that you know the basics, it’s easy to customize your Roundabout to fit better into your site. While each example below only lists one or two options at a time, you can combine as many effects as you’d like into one big set of customization options.

Start Wherever

By default, your Roundabout will start with the first moveable item in focus, but this doesn’t have to be the case. Change which moveable item starts in focus by setting the startingChild option. Set this to the zero-based position of the child (as listed among all of the children that can move in the Roundabout).

For example, continuing our three-step example above, if we want the Roundabout to start on the <li> containing “Box 3”:

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         startingChild: 2 // the third box, so: 0, 1, *2*
      });
   });
   // ]]>
</script>

Speed Up, Slow Down

If your animations aren’t happening at the right speed, you can easily make them faster or slow them down with the duration option.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('div.moveMe').roundabout({
         duration: 1200 // in milliseconds, of course
      });
   });
   // ]]>
</script>

Opacity & Scale

To make your Roundabout more (or less) dramatic, you can set the minimum and maximum values for your moveable items’ opacity and scale.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         minOpacity: 0.0, // invisible!
         minScale: 0.1 // tiny!
      });
   });
   // ]]>
</script>

Moveable items exactly opposite of the focusBearing will have whatever is set as the minScale, minOpacity and minZ applied as their values for scale, opacity and z-index (respectively). Try adjusting from the default settings for each until you find something that you like.

Triggering Roundabout Animations

There are two settable options that let you easily trigger the Roundabout to animate to the next and previous moveable item. Use the btnNext option to connect any element’s click event to animate the Roundabout to the next moveable item not in focus. Use the btnPrev to do the same thing in the other direction.

To continue the example from the three-step process above, add two links under the unordered-list.

<a href="#" id="next">Next!</a>
<a href="#" id="previous">Previous!</a>

Now, set btnNext and btnPrev options to connect your links to your Roundabout. You can enter any selector you’d like, as this is getting passed straight to jQuery on the inside.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         btnNext: '#next',
         btnPrev: '#previous'
      });
   });
   // ]]>
</script>

Simple as that. Now, when a user clicks on either your “Next!” or “Previous!” links, your Roundabout will move like they’re clicking on boxes in the Roundabout itself.

Don’t Let Users Click

Clicking on out-of-focus items in your Roundabout will cause them animate into focus by default, but this can be turned off if you’re not into that kind of thing.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         clickToFocus: false
      });
   });
   // ]]>
</script>

When this is true (as it is in its default state), links clicked on within out-of-focus moveable items will be short-circuited and the animation will happen instead. If you turn this false (as in the example above), links will work no matter what their position around the Roundabout.

“In Focus” is Relative

While the default value is set to be the item that appears closest to you, you can set the focusBearing to be any angle. Try this configuration, and then see where things point:

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         focusBearing: 90.0
      });
   });
   // ]]>
</script>

Not Just For Lists

While using a <ul> or <ol> is the default set up, you can apply Roundabout to anything. To do so, attach .roundabout(); onto a jQuery selection of any element type you wish (let’s say a special <div> with the class moveMe. To tell Roundabout which child objects you wish to move around, use the childSelector option to pass a string that jQuery can use to select all of this element’s children.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('div.moveMe').roundabout({
         childSelector: 'div.moveable'
      });
   });
   // ]]>
</script>

This example will look inside of any <div class="moveMe"></div> for any <div class="moveable"></div> and will use those elements to move around. The childSelector option is literally being passed to jQuery on the inside, so any valid jQuery selector will work here.

One advantage to not using lists is that you can place other items inside your holder-elements. By absolutely positioning these elements in the right spot, you can have your moveable-elements moving around these positioned elements!

Using the jQuery Easing Plugin

Don’t get me wrong, jQuery’s built in easing techniques are nice, but to get the most bang for your buck you should check out the jQuery Easing plugin. The implementation is simple.

First, include the easing script.

<script type="text/javascript" src="jquery.easing.1.3.js"></script>

Copy & Paste Warning!

Your file’s name, file path and version may vary.

Second, set the easing option in your roundabout.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         easing: 'easeInOutExpo'
      });
   });
   // ]]>
</script>

Use any of the easing names provided by the plugin and Roundabout will do the rest. Learn more about these names here.

Roundabout Shapes

Roundabout can now do more than just turntables. Check out the Roundabout Shapes plugin for more paths along which your moveable items can travel. There are also instructions on how to use different shapes as well.

(It’s easy, I promise.)

Advanced Techniques

Ready to knock it out of the park? Here are a couple of more advanced ways that you can use Roundabout to really wrangle its true power.

See Exactly What’s Going On

If you wish to dive deeper into what makes Roundabout tick, turn on debugging.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         debug: true
      });
   });
   // ]]>
</script>

This will change the HTML in your moving elements to a full slate of styling information.

Move Things the Other Way Added in v1.1

If you don’t like the way Roundabout moves, you can reverse its direction by using reflect.

<script type="text/javascript">
   // <![CDATA[
   $(document).ready(function() {
      $('ul').roundabout({
         reflect: true
      });
   });
   // ]]>
</script>

This will reverse the way the moveable-items are places around the shape, and will reverse the way roundabout_animateToNextChild and roundabout_animateToPreviousChild work.

Hooking Into Events

Two events can fire during each jQuery animation. A moving item’s focus event will be fired if it completes an animation in the focus position. A moving item’s blur event will be fired if it starts an animation in the focus position and moves off of it.

Two notes of caution about events:

  1. The first focus event will occur once .roundabout() is called, so be sure to set up all event handling prior to attaching Roundabout.
  2. The events listed above can fire during each animation, but are not guaranteed to do so. However, this will only occur in situations of more complex animations where moveable items aren’t starting and stopping in focus.

Methods for Advanced Control

Aside from the standard animation that comes turned on by default, a roundabout can be controlled by more than just buttons. A number of methods can be used to change the way the Roundabout is positioned.

These methods affect any Roundabout-enabled elements that are included in your jQuery selector, and all of these methods can be inserted anywhere into a standard chain of jQuery method calls. These examples use ul as a sample selector, but as you’ll so smartly recall: anything can be put there.

But quickly, before we get to the methods…

im in ur [jQuery], killin ur [namespaces]

It’s been brought to my attention that the following methods are not the right way to handle altering your Roundabouts. The right way is to either change the functionality of .roundabout() based upon what gets passed in or to store a Roundabout object internally that you can grab and then play with from there.

That makes sense to people that know JavaScript pretty well, but I find it to be confusing for those that just want to make things move. So, I’m doing things the “naughty” way. I’m not proud of it, but I value easy-usability over because-that’s-how-you’re-supposed-to-do-it.

So, to combat stepping on toes, all of the Roundabout methods start with roundabout. I hope these make using Roundabout as easy as I intend, or at least easy enough to justify doing things the not-so-right way.

Set Bearing

$('ul').roundabout_setBearing(float newBearing);

Sets the current bearing of the Roundabout to newBearing. This is used as a step function within animations, but can also work well, for example, as being set to a slider’s value.

Set Tilt

$('ul').roundabout_setTilt(float newTilt);

Sets the current tilt of the Roundabout to newTilt. This value is less mathematically precise than the other calculations, and thus will probably take some fidgeting to get right. Also a good candidate for being set to a slider’s value.

Adjust Bearing

$('ul').roundabout_adjustBearing(float delta);

Sets the current bearing by changing the value delta degrees. This value can be positive or negative to move in both directions.

Adjust Tilt

$('ul').roundabout_adjustTilt(float delta);

Sets the current tilt by changing the value by delta. This value can be positive or negative to move in both directions.

Animate to Bearing

$('ul').roundabout_animateToBearing(float bearing[, int duration[, string easing]]);

Changes the Roundabout’s bearing by animating to it. Will use the Roundabout’s default values for duration and easing if none are provided.

Animate to Delta

$('ul').roundabout_animateToDelta(float delta [, int duration[, string easing]]);

Changes the Roundabout’s bearing by delta degrees by animating to it. Will use the Roundabout’s default values for duration and easing if none are provided.

Animate to Child

$('ul').roundabout_animateToChild(int child[, int duration[, string easing]]);

Changes the Roundabout’s bearing to a zero-based child’s bearing by animating to it. Will use the Roundabout’s default values for duration and easing if none are provided.

Animate to Next Child

$('ul').roundabout_animateToNextChild([int duration[, string easing]]);

Changes the Roundabout’s bearing by animating to the next child’s position (traveling counterclockwise). Will use the Roundabout’s default values for duration and easing if none are provided.

Animate to Previous Child

$('ul').roundabout_animateToPreviousChild([int duration[, string easing]]);

Changes the Roundabout’s bearing by animating to the previous child’s position (traveling clockwise). Will use the Roundabout’s default values for duration and easing if none are provided.

Animate Angle to Focus

$('ul').roundabout_animateAngleToFocus(float target[, int duration[, string easing]]);

Changes the Roundabout’s bearing by animating a given angle to focus. Will always take the shortest route (clockwise or counterclockwise). Will use the Roundabout’s default values for duration and easing if none are provided.

Option Reference

The following is a complete list of settable options for your Roundabout, each with a description as to what it controls, its expected data type and its default value.

Option Description Data Type Default
bearing The starting direction in which the Roundabout should point. float 0.0
tilt The starting angle at which the Roundabout’s plane should be tipped. float 0.0
minZ The lowest z-index value that a moveable item can be assigned. (Will be the z-index of the item farthest from the focusBearing.) integer 100
maxZ The greatest z-index value that a moveable item can be assigned. (Will be the z-index of the item in focus.) integer 100
minOpacity The lowest opacity value that a moveable item can be assigned. (Will be the opacity of the item farthest from the focus bearing.) float 0.4
maxOpacity The greatest opacity value that a moveable item can be assigned. (Will be the opacity of the item in focus.) float 1.0
minScale The lowest percentage of font-size that a moveable item can be assigned. (Will be the scale of the item farthest from the focus bearing.) float 0.4
maxScale The greatest percentage of font-size that a moveable item can be assigned. (Will be the scale of the item in focus.) float 1.0
duration The length of time (in milliseconds) that all animations take to complete by default. integer 600
btnNext A jQuery selector of elements that will have a click event assigned to them. On click, the Roundabout will move to the next child (counterclockwise). string null
btnPrev A jQuery selector of elements that will have a click event assigned to them. On click, the Roundabout will move to the previous child (clockwise). string null
easing The easing method to be used for animations by default. jQuery comes with “linear” and “swing,” although any of the jQuery Easing plugin’s values can be used if the easing plugin is included. string 'swing'
clickToFocus When an item is not in focus, should it be brought into focus via an animation? If true, will disable any click events on elements within the moving element that was clicked. Once the element is in focus, click events will no longer be blocked. boolean true
focusBearing The bearing at which a moving item’s position must match on the Roundabout to be considered “in focus.” float 0.0
shape For use with the Roundabout Shapes plugin. Sets the shape of the path over which moveable items will travel. string 'lazySusan'
debug Changes the HTML within moving elements into a list of information about that element. Helpful for advanced configurations. boolean false
childSelector Changes the set of elements Roundabout will look for within the holding element for moving. string 'li'
startingChild Starts a given child at the focus of the Roundabout. This is a zero-based number positioned in order of appearance in the HTML file. integer 0
reflect Added in v1.1 Setting to true causes the elements to be placed around the Roundabout in reverse order. Also flips the direction of “next” and ”previous” buttons. boolean false

Things I’ve Found

Change Log

v1.1 Mar 13, ’10
  • Added reflect as a configurable option.
  • Element values are not stored in jQuery’s .data() method instead of being custom attributes.
  • Fixed a bug that was cauing roundabout_animateToNextChild and roundabout_animateToPreviousChild to stop functioning in certain scenarios.
v1.0 Dec 16, ’09
  • First release.