function addClassName(el, sClassName) {
    var s = el.className;
    var p = s.split(" ");
    var l = p.length;
    for (var i = 0; i < l; i++) {
            if (p[i] == sClassName)
                    return;
    }
    p[p.length] = sClassName;
    el.className = p.join(" ");
}

function removeClassName(el, sClassName) {
    var s = el.className;
    var p = s.split(" ");
    var np = [];
    var l = p.length;
    var j = 0;
    for (var i = 0; i < l; i++) {
            if (p[i] != sClassName)
                    np[j++] = p[i];
    }
    el.className = np.join(" ");
}

function frenchFloatConverter( s ) {
        var value = s.match( /-?[0-9]+[\.,][0-9]+/ );
        if( null != value ) {
            return parseFloat( value[0] );
        }
}

function frenchDateConverter( s ) {
        var parts = s.split("/");
        var d = new Date(0);
        d.setFullYear(parts[2]);
        d.setDate(parts[0]);
        d.setMonth(parts[1] - 1);
        return d.valueOf();
};

function frenchTimeConverter( s ) {
        var parts = s.split(":");
        var d = new Date(0);
        d.setHours(parts[0]);
        d.setMinutes(parts[1]);
        d.setSeconds(parts[2]);
        return d.valueOf();
};

function shortFrenchDateTimeConverter( s ) {
        var parts = s.split(" ");
        var d = new Date(0);

        var date = parts[0].split("/");
        d.setDate(date[0]);
        d.setMonth(date[1] - 1);
        d.setFullYear(date[2]);

        var time = parts[1].split(":");
        d.setHours(time[0]);
        d.setMinutes(time[1]);

        return d.valueOf();
};

function fileSizeConverter( s ) {
    var parts = s.split(" ");
    var multiplier = 1;

    switch( parts[1] ) {
        case 'Ko':
            multiplier = 1024;
            break;
        case 'Mo':
            multiplier = 1024*1024;
            break;
        case 'Go':
            multiplier = 1024*1024*1024;
            break;
    }
    return parseFloat( parts[0] ) * multiplier;
};

function getCheckBoxValue (oRow, nColumn) {
        return oRow.cells[nColumn].firstChild.checked ? 1 : 0;
};

SortableTable.prototype.addSortType( "SmartFloat", frenchFloatConverter );
SortableTable.prototype.addSortType( "FrenchDate", frenchDateConverter );
SortableTable.prototype.addSortType( "FrenchTime", frenchTimeConverter );
SortableTable.prototype.addSortType( "ShortFrenchDateTime", shortFrenchDateTimeConverter );
SortableTable.prototype.addSortType( "CheckBox", null, null, getCheckBoxValue );
SortableTable.prototype.addSortType( "SmartFileSize", fileSizeConverter );

SortableTable.prototype.zebra = function() {
    var rows = this.tBody.rows;
    var l = rows.length;
    for (var i = 0 ; i < l ; i++) {
        removeClassName( rows[i], ( i % 2 == 0 ) ? "odd" : "even");
        addClassName( rows[i], ( i % 2 == 0 ) ? "even" : "odd");
    }
}

// IE does not remember input values when moving DOM elements
if( !( /Opera/.test( navigator.userAgent ) ) && ( /MSIE/.test( navigator.userAgent ) ) ) {
    var ieArray = new Array();

    // backup check box values
    SortableTable.prototype.onbeforesort = function () {
        var table = this.element;
        var inputs = table.getElementsByTagName("INPUT");
        var l = inputs.length;
        for ( var i = 0; i < l; i++ ) {
            //inputs[i].parentNode.parentNode._checked = inputs[i].checked;
            ieArray[inputs[i].id+" "+inputs[i].name+" "+inputs[i].value] = inputs[i].checked;
        }
    };

    // restore check box values
    SortableTable.prototype.onsort = function () {
        var table = this.element;
        var inputs = table.getElementsByTagName("INPUT");
        var l = inputs.length;
        for ( var i = 0; i < l; i++ ) {
            //inputs[i].checked = inputs[i].parentNode.parentNode._checked;
            inputs[i].checked = ieArray[inputs[i].id+" "+inputs[i].name+" "+inputs[i].value];
        }
        this.zebra();
    };
}
else {
    SortableTable.prototype.onsort = function () {
        this.zebra();
    };
}