11 October 2009

Shortening content to fit with JavaScript

Very often when working in an application, you deal with data of variable length. File names provided by users, titles that can be arbitrarily long, all these need to be catered for.

Fitting this variable length data into a grid or fixed layout in a web interface can be problematic. The current crop of browsers only has limited support for shortening content so it can fix in a fixed amount of space.

This week I’ve been working on a more general mechanism for shortening text until it fits within a predefined width. Specifically, I need a solution that worked for breadcrumbs where there was a maximum total width for the breadcrumb, and the left-most breadcrumb items are less important than the right-most. Therefore, the left-most breadcrumbs should be abbreviated first.

Here’s a demonstration of the JavaScript I came up with: abbreviation demo.


Before abbreviation


After abbreviation

The JavaScript to shorten text this way is quite simple. It uses jQuery for simplicity, but would work quite well in core JavaScript as well. Below is the guts of the algorithm.

function abbreviateUntil(element, condition) {
    var children = $(element).children();
    var current = 0;
    while (current < children.length && !condition.call(element)) {
        var $child = $(children[current]);
        if ($child.text() == "\u2026") {
            current++;
            continue;
        }
        if (!$child.attr("title")) $child.attr("title", $child.text());
        $child.text($child.text().replace(/[^\u2026]\u2026?$/, "\u2026"));
    }
}

In the real implementation, this function is wrapped in a jQuery plugin that you use like this:

var fixedWidth = $(".fixed").width();
$(".fixed ul").abbreviateUntil(function () {
    return $(this).width() <= fixedWidth;
})

More information on how to use the code and how to construct the markup and styles is available on the demo page. Please let me know If you have any ideas on how to make this more generally useful.