Collision prevention using jQuery.

I was building a graph with Flot.js and wanted to display descriptive labels, placed above some vertical lines inside the graph, inside a gutter. I ran into the problem that, as the positioning of these labels was absolute, these labels would regularly overlap each other, making them unreadable. By setting a bottom css value for each label (eg. vertically positioning the labels) I could have placed labels on top of another, but this required doing this manually for each label, something that is not possible when creating a dynamic graph that changes every x hours/days/weeks/years. I had to come up with another solution.

This is why I developed a jQuery plugin that does, what I call, ‘Collision Detection’, which:

Enumerates all the labels

Orders the labels based on the order they appear visually (based on the left css property)

Takes each label and determines if the next label will overlap it, and if so, move the next label up a level

Checks if that next level has room for the label (eg. checks if that level does not already have a label in it that this label would subsequently overlap) and moves the label up a level again if it does not fit, repeating this until it finds a level in which the label will fit

Finally, calculates the required height for each level, and sets that as a bottom css position for each element in the next level

I did not want to introduce any new elements (like a wrapper div for each level), so the plugin will basically leave everything untouched, besides setting two CSS properties for the elements concerned.

Demo

Click here for a demo.
The demo features a set of labels that overlap. Click the ‘demo’ button to run with the default settings and watch the labels get sorted and positioned so there is no overlapping, while the labels’ pointers are still at the intended position.
You can click the ‘randomize’ button to randomize the position of the labels, after which you can run one of the demo’s again.

Note: the animations are for demo purposes, and are not handled by the plugin but by the demo CSS.

Usage

Copy the code (see below) to a JS file (like hnl.collision.detection.js) and include it in your project. Then, to initiate the collision detection:

$('elementContainingLabels').CollisionDetection();

(Of course replacing ‘elementContainingLabels’ for your own element. In the demo it is the element with class gutter.)

Options

You can pass one option to the plugin that will determine the spacing between the labels. It is aptly named spacing. This value defaults to 1, and will accept negative spacing (see demo). Example: $('elementContainingLabels').CollisionDetection({spacing:10});

Work to be done

The plugin is pretty straightforward and basic, though I still would like to add some functionality, like aligning the labels from top to bottom as opposed to how it is now (bottom to top). I’ll update the code when I get around to that.