JQuery columnizeList Plugin

I’ve spent a rainy german saturday hacking away on my dusty ol’ website. Because of the current layout without sidebars, I had to find an unobtrusive place for meta-information like tags or archive-links. Those chunks of information can grow quite large, so i decided to expand into length rather than height and go multi-column for longer lists. Before I fully understood the stony way that lay before me, I’ve found an article on “A List Apart”-magazine outlining different ways to tackle this problem. Because of lacking support for true multi-columns we have to resort to some slightly hacky CSS, either floating or applying negative margins.

My solution works with negative margins, but automatically applied through a JQuery-plugin (see example below). It seems to be rather stable across browsers, but has the usual quirks of using CSS for something its not intended to perform - make sure to read about the CSS-limitations of this method over at “A List Apart”. By the way, you can see this plugin in action through the “archive”-area at the top of this website

Features

  • Styling of ordered/unordered lists
  • Configurable column-count and width
  • Resize-friendly em-based sizing
  • Easy restoring to “non-column” layout
  • Automatic adjustment on DOM-modification of the list (Firefox only)
  • Requirements: JQuery 1.2 (download)
  • Browser-Compatibility: Firefox 1.5+, IE6+, Safari 2

Usage

Just apply to any group of DOM-elements gathered by the amazing JQuery-selectors. The provided arguments are optional (these are the default values).

$('#demolist').columnizeList({cols:3,width:13,unit:'em'});

Example

  1. harold (3550)
  2. horatio (1320)
  3. hitler (1120)
  4. henry (784)
  5. hector (358)
  6. haploid (315)
  7. hopping (50)
  8. herbert mulroney (44)
  9. hopscotching (29)
  10. hominibus (19)
  11. honkey (19)
  12. hermoine (18)
  13. hieronymus (13)
  14. halliburton (12)
  15. hummer (10)
  16. harlod (10)
  17. heironymious (9)
  18. hemorrhoids (7)
  19. hammersack (6)

Just in case you’re wondering: The demo-list consists of the most common fillers for the phrase “Jesus H Christ” ;-)

Sourcecode

/**
 * Copyright (c) 2007 Ingo Schommer (www.chillu.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Splits a /-list into equal-sized columns.
 * 
 * Requirements: 
 * 
 * All list-elements need to have the same height.
 * List has to be blocklevel
 * 
 * 
 * Caution: margin-top/margin-left on  are overridden.
 * Doesn't react to changes to the DOM, you need to call the function
 * manually afterwards.
 * 
 * @see http://www.alistapart.com/articles/multicolumnlists
 */
jQuery.fn.columnizeList = function(settings){
    settings = jQuery.extend({
        cols: 3,
        width: '13',
        unit: 'em'
    }, settings);

    var prevColNum = 0;
    var size = $('li',this).size();
    var computedColHeight = 0;
    var baseFontSize = parseFloat($(this).css('font-size'));
    $('li',this).each(function(i) {
        var currentColNum = Math.floor(((i)/size) * settings.cols);
        $(this).css('margin-left',(currentColNum*settings.width)+''+settings.unit);
        if(prevColNum != currentColNum) {
            $(this).css('margin-top','-'+(computedColHeight/baseFontSize)+'em');
            computedColHeight = $(this).height();
        } else {
            $(this).css('margin-top','0');
            computedColHeight += $(this).height();
        }
        prevColNum = currentColNum;
    });

    this.css('height',(size/settings.cols)*(parseFloat($('li:first',this).height())/baseFontSize)+'em');
    this.after('');

    var onchange = function(e) {
        if(!e.originalTarget || e.originalTarget.tagName != 'LI') return true;
        var scope = this; // caution: closure
        setTimeout(function() {$(scope).columnizeList(settings);}, 50);
    };

    this.one('DOMNodeInserted',onchange);
    this.one('DOMNodeRemoved',onchange);

    return this;
};

jQuery.fn.uncolumnizeList = function(){
    $('li',this).each(function(i) {
        if(!$(this).attr('style')) return;
        $(this).attr(www.chillu.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Splits a /-list into equal-sized columns.
 * 
 * Requirements: 
 * 
 * All list-elements need to have the same height.
 * List has to be blocklevel
 * 
 * 
 * Caution: margin-top/margin-left on  are overridden.
 * Doesn't react to changes to the DOM, you need to call the function
 * manually afterwards.
 * 
 * @see http://www.alistapart.com/articles/multicolumnlists
 */
jQuery.fn.columnizeList = function(settings){
    settings = jQuery.extend({
        cols: 3,
        width: '13',
        unit: 'em'
    }, settings);

    var prevColNum = 0;
    var size = $('li',this).size();
    var computedColHeight = 0;
    var baseFontSize = parseFloat($(this).css('font-size'));
    $('li',this).each(function(i) {
        var currentColNum = Math.floor(((i)/size) * settings.cols);
        $(this).css('margin-left',(currentColNum*settings.width)+''+settings.unit);
        if(prevColNum != currentColNum) {
            $(this).css('margin-top','-'+(computedColHeight/baseFontSize)+'em');
            computedColHeight = $(this).height();
        } else {
            $(this).css('margin-top','0');
            computedColHeight += $(this).height();
        }
        prevColNum = currentColNum;
    });

    this.css('height',(size/settings.cols)*(parseFloat($('li:first',this).height())/baseFontSize)+'em');
    this.after('');

    var onchange = function(e) {
        if(!e.originalTarget || e.originalTarget.tagName != 'LI') return true;
        var scope = this; // caution: closure
        setTimeout(function() {$(scope).columnizeList(settings);}, 50);
    };

    this.one('DOMNodeInserted',onchange);
    this.one('DOMNodeRemoved',onchange);

    return this;
};

jQuery.fn.uncolumnizeList = function(){
    $('li',this).each(function(i) {
        if(!$(this).attr('style')) return;
        $(this).attr('style', 
            $(this).attr('style')
            .replace(/margin\-left[^,]*/g,'')
            .replace(/margin\-top[^,]*/g,'')
        );
    });
    $('ul',this).each(function(i) {
        if(!$(this).attr('style')) return;
        $(this).attr('style', 
            $(this).attr('style')
            .replace(/[^-]height[^,]*/g,'')
        );
    });
    $(this).height('auto');
    this.unbind('DOMNodeInserted');
    this.unbind('DOMNodeRemoved');

    return this;
}
This was posted 2 years ago. It has 0 notes.

Outage - Teh PAIN!

Well, switching my blog to Mephisto was one thing, but taming a fastcgi-server on my shared-hosting-provider Site5 is a completely different story. Being the usual geek, I’ve applied way too much technology to a simple problem: Capistrano promises a solid automated deployment process, and is often used for Rails-based apps. Very interesting concept, and for more scientific than practical reasons I’ve spend nearly two days configuring this tool for chillu.com. Well, i’ve ended up 90% done, and an embarassing downtime while debugging fastcgi and mysterious rails-logs – sorry for that!

This was posted 2 years ago. It has 0 notes.

shutdown -h now!

Whew, what a geeky weekend: I was in Berlin all the time, well…over internet-console. Certain circumstances (and a notion of self-destruction) brought me to reinstall my root-server at Strato/Berlin, complete with nine (partly commercial) websites and loads of email-adresses on it. Its about every webmasters nightmare, and took me one day preperation (backup, user-accounts, etc) and even more for the new setup. So, again a weekend lost to web-work – which happens too often in the last months. University starts again tomorrow, it’s getting fall – and I somehow missed out the complete summer being heads-down in projects. DAMN COMPUTERS!

This was posted 5 years ago. Notes.

Updates!

After finishing the chillu.com-redesign in late june I was really busy with several projects. Most of them are already in the works-section, but they will be subject of a different post (too tired now). So…again under pressure: Applications for my internship in 2005 are in their making, and chillu.com will be my showcase – finally it’s useful to have a website :D On the updates: IE-users rejoice! If you are not already cut off from the internet by dialers, worms or malicous JPEG-Image (lol, by the way), you now get the full functionality in the “works”-section (fixed some javascript-errors). That’s it for today – watch out for more frequent posts in the future!

This was posted 5 years ago. Notes.

Finally online

A study-project kinda forced me to finish off the chillu.com-redesign – and here it is! Colours are a more vivid and friendly that in the night-theme of the old version. In general everything is polished a bit: All content is generated by the Content-Management-System Typo3, the Portfolio-Section is updated and beefed up. Browser-Optimization is not yet finshed (problems with IE5 and IE6 *sigh). Apart from that: Mi casa es su casa! Take a look around – and please give me feedback!

This was posted 6 years ago. It has 0 notes.

MyPortfolio-Extension nearly finished

Typo3 has great expandability, which I used to incorporate my own extension. bla blubb

This was posted 6 years ago. Notes.

Website Prototype

The Website-Prototype for a newly-structured chillu.com seems to approach the end! With quite some work I tried to persuade Typo3 to give me DAMN CONTROL over layout and positioning of the page elements back. I didn’t lose this fight, but I’m far from winning either. Whatever…

This was posted 6 years ago. Notes.