To The Cloud, Sort Of!

I’d like to take a moment here to hang my hat on the trend of using the word “Cloud” in an attention-getting yet technically misleading way. That is, if it’s all the same to you.

Partly Cloudy

I’m actually going to be showing you how I used jQuery to build an attractive data cloud out of an unassuming list of links, in a way that has nothing at all to do with Windows Azure, the contemporary batch of Windows 7 television commercials, or even evil weather control machines. But the good robots at Bing and Google don’t really need to know about that, now, do they?

The Boring Bit

For those of you who didn’t show up for an article on evil weather control machines, let’s say I’ve got some items in a list, perhaps song titles with some attribute-bound play count data culled from my iTunes database:

<ul class="cloud">
    <li><a href="#" data-count="18">Mouth for War</a></li>
    <li><a href="#" data-count="26">A Song For The Dead</a></li>
    <li><a href="#" data-count="18">Ænema</a></li>
    <li><a href="#" data-count="25">Allegro Concerto #3</a></li>
    <li><a href="#" data-count="22">Appalachian Spring</a></li>
    <li><a href="#" data-count="23">Blackened</a></li>
    <!—- etc. -->
    <li><a href="#" data-count="31">Welcome</a></li>
    <li><a href="#" data-count="25">Welcome To The Black Parade</a></li>
    <li><a href="#" data-count="17">Wish You Were Here</a></li>
</ul>

Sure, I can go ahead and display that on my site as-is. But without a quick visual of how each title is related to its neighbor in the hierarchy of my personal preference, anyone visiting the site would instantly slip into a boredom coma.

boredom-coma

Sorry! Here’s a picture of steampunk R2-D2 to bring you back:

Wasn’t that engaging? Seriously. Stick with me.

Fn Data Cloud, Bro

Because all the hip kids with their well-worn and reusable jQuery code are doing it, we’re going to make a proper plug-in out of this script. I won’t bore you with the ins/outs of jQuery plug-in making except to link over to their official guidelines, and to add a subtle note directing you to the bottom of that page where they ever so concisely cover the correct pronunciation of fn. Giggle.

First, we’ll add a JavaScript file (call it jquery.dataCloud.js) and frame out the dataCloud method:

(function ($) {
    $.fn.dataCloud = function (options) {

        // TODO: parse options

        // TODO: find the maximum value in the set

        // TODO: for each item,

        // get its value,
        // calculate its font size as a proportion within the given range

    };

})(jQuery);

Then we can define the arguments to the method using an object literal and the jQuery extend function. These include the minimum and maximum font sizes for the cloud (in ems here), and the name of the attribute on the item that contains the data:

// parse options
var settings = {
    min : 1,
    max : 4,
    attribute : "data-value"
};
$.extend(settings, options);

Since it’s going to come in handy very shortly, here’s a function we’re going to use to safely get that data value from each item in the list.

// a function to retrieve the value from the given element
getValue = function(item) {
    return parseInt(item.attr(settings.attribute));
};

Okay, now, sit up—this is the good part. So, in order to base the font size of an item on its relationship to the largest value in the set, we must first find the largest value in the set. That’s what the first each is about. Then, in the second, we do a little math, a miracle occurs, and we apply the calculated font size to each item:

// find the maximum value in the set
var max = 0;
return this.each(function() {
    var value = getValue($(this));
    if (value > max) max = value;

}).each(function() {    // for each item,

    // get its value,
    var value = getValue($(this));

    // calculate its font size as a proportion 
    // within the given range
    var percent = value / max;
    var range = settings.max - settings.min;
    var size = settings.min + (range * percent) + "em"; // math is hard

    $(this).css("font-size", size);

});

For those among you who have had their left hand paused over Ctrl+C this whole time, here is the whole thing:

; (function ($) {
    $.fn.dataCloud = function (options) {
        /// <summary>
        /// Scales the font size of items in a list 
        /// according to their relative value.
        /// </summary>
        // parse options
        var settings = {
            min : 1,
            max : 4,
            attribute : "data-value"
        };
        $.extend(settings, options);

        // a function to retrieve the value from the given element
        getValue = function(item) {
            return parseInt(item.attr(settings.attribute));
        };

        // find the maximum value in the set
        var max = 0;
        return this.each(function() {

            var value = getValue($(this));
            if (value > max) max = value;

        }).each(function() {    // for each item,

            // get its value,
            var value = getValue($(this));

            // calculate its font size as a proportion 
            // within the given range
            var percent = value / max;
            var range = settings.max - settings.min;
            var size = settings.min + (range * percent) + "em";

            $(this).css("font-size", size);

        });
    };
})(jQuery);

Now let’s lay this listing on our listless list, like so:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="./jquery.dataCloud.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $(".cloud a").dataCloud({
            min: 0.1,
            max: 2,
            attribute: "data-count"
        });
    });
</script>

The songs are now rendered in sizes that reflect precisely how much iPod love I have given them.

cloud-sizes

Yes, the Star Wars Cantina Band jam is on par with Herr Mozart. Don’t judge me.

And One More Thing

Here’s a light dusting of CSS to give our cloud a hint of personality:

body { text-align: center; }

a { text-decoration: none; }

ul { padding-left: 0px; }

.cloud {
    font-family: Verdana;
    width: 400px;
    margin: auto;
}

.cloud li {
    display: inline;
    list-style: none;
    margin-right: 15px;
    white-space: nowrap;
}

Now everyone knows what I’ve been doing with my ears, and we have a nice data cloud plug-in to write home about.

cloud-css

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s