Return to Snippet

Revision: 14969
at June 18, 2009 15:14 by beneberle


Updated Code
/* Javascript File  

        Table actions plug-in v0.8 by frequency-decoder.com

        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)

        Please credit frequency decoder in any derivative work - thanks

        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.

        NOTE: Parts of this script is based on a script originally developped by the veritable Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html)

-----------*/

/*
Zebra striping  

To zebra stripe every alternate table row, just give the table a className of the form rowstylealt-XXX where XXX represents the className to give each alternate row, for example; giving the table a className of rowstylealt-alt will give each alternate row the class alt.
i.e...

<table class="rowstylealt-bluetr".....  

with a style: 
.bluetr {background:#e8f7ff;}

Row Highlighting

To highlight the current row i.e. the row the mouse is currently hovering over; just give the table a className of the format rowstylehover-XXX, where XXX represents the class that will be given to the current cell’s parent TR node.

Column Highlighting

To highlight the current column, just give the table the className colstylehover-XXX, where XXX represents the class that will be given to each node within the current column scope.

Highlighting the “current” cell

To highlight the current cell, just give the table a className of the format cellhover-XXX, where XXX represents the className that will be given to the current cell.

Row selection

To enable users to click on a row in order to “select” it, just give the table a className of the format rowselect-XXX, where XXX represents the class to give the current cell’s parent TR node after the click event has fired.
Multiple row selection

Whenever the Shift key is held down, users can click and drag the mouse pointer in order to select multiple rows simultaneously. The callback function will be called on the selection of each new row and not just when the drag action has stopped.
Disabling text selection in Internet Explorer

I’ve currently hijacked Internet Explorer’s proprietary onselectstart and ondrag events in order to stop the selection of text during the drag action. If other applications are also using these events, you may have to tweak the code to stop it from overwriting handlers already set for these events… and yes, I know hijacking events using old-school methods is wrong.
Single row selection only

Should you wish that only one table row can be selected at a time, give the table the class rowselectsingle. This, of course, means that holding the Shift key to select multiple rows will not work.
The callback function

Enabling users to select table rows is rather dull if nothing can be done with the user’s selection. To this end, the script enables you to define a reference to a JavaScript callback function (or Object method) that is itself passed an Object detailing the table, the cell clicked, the row clicked, the action to be taken (i.e. add or remove the row from the list of currently selected rows) and the list of currently selected table rows i.e:

  
 // The following Object is passed to the callback function
 {
      "table":   /* The table */,
      "cell":    /* The cell that was clicked */,
      "row":     /* The row to be added or removed */
      "remove":  /* Are we attempting to remove the row (T/F) */
      "rows":    /* An array of currently selected TR nodes */
 }
  
  

The callback function should always return a Boolean value that indicates to the script if it should continue with the add or remove action. This enables you to filter out rows from the selection using bespoke criteria.
Stipulating the callback function

Should you wish to define a specific callback function for the table, just give the table a className of the format rowselectcallback-XXX, where XXX represents the name of the JavaScript function to call after a row has been selected or deselected by the user.
Stipulating an Object.method as a callback function

Should you wish to define an Object method as a callback function, just give the table a className of the format rowselectcallback-XXX, where XXX represents the name of the JavaScript Object method to call after a row has been selected or deselected by the user.

In order to enable the parsing of the “.” (dot) Object notation, the XXX className has all “-” characters replaced by the “.” character, for example; giving the table the className rowselectcallback-anObject-aMethod will mean that the script will attempt to use anObject.aMethod() as the callback function.

An example of defining an Object method in this way can be viewed within the table actions demo. Just look at the source code to see how it was done.
Programmatically clearing selected rows

Should you wish to programmatically remove the user’s selection, just call the method fdTableActions.deselectAllRows, passing in the ID of the table as an argument, for example; calling fdTableActions.deselectAllRows('testTable'); will remove the user selection for the table with an ID of “testTable”.

-----------*/




var fdTableActions = {
        tableCache:{},
        init:function() {
                var tables = document.getElementsByTagName("table");
                var rowAlt, colHover, rowHover, rowSelect, rowSelectCallback, cellHover, rowList, rowArr, colObj, elem, rowLength, workArr, celCount, rowSpan, colSpan, cel, colHead, rowL, colL;
                var uniqueID = 0;
                var colspan = "colspan";
                var rowspan = "rowspan";
                /*@cc_on
                /*@if(@_win32)
                colspan = "colSpan";
                rowspan = "rowSpan";
                /*@end
                @*/

                for(var k = 0, table; table = tables[k]; k++) {
                        // Grab the className for the alternate rows
                        rowAlt  = table.className.search(/rowstylealt-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylealt-([\S]+)/)[1];
                        // Highlight columns?
                        colHover  = table.className.search(/colstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/colstylehover-([\S]+)/)[1];
                        // Grab the className for the rowStyleHover
                        rowHover  = table.className.search(/rowstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylehover-([\S]+)/)[1];
                        // Do we select the rows
                        rowSelect = table.className.search(/rowselect-([\S-]+)/) == -1 ? "" : table.className.match(/rowselect-([\S]+)/)[1];
                        // Single or multiple row selection possible
                        rowSelectSingle = table.className.search(/rowselectsingle/) != -1;
                        // Do we have a callback for this table whenever a row is selected?
                        rowSelectCallback = table.className.search(/rowselectcallback-([\S-]+)/) == -1 ? "" : table.className.match(/rowselectcallback-([\S]+)/)[1];
                        // Replace "-" with "." to enable Object.method callbacks
                        rowSelectCallback = rowSelectCallback.replace("-", ".");
                        // Current TH or TD
                        cellHover = table.className.search(/cellhover-([\S-]+)/) == -1 ? "" : table.className.match(/cellhover-([\S]+)/)[1];

                        // Do we even need to continue?
                        if(!(rowAlt || rowHover || colHover || rowSelect || cellHover)) continue;

                        // Create a table ID if necessary
                        if(!table.id) table.id = "fdTable-" + uniqueID++;

                        // Cache this tables details
                        fdTableActions.tableCache[table.id] = { "trCache":[], "rowSelectSingle":rowSelectSingle, "rowSelect":rowSelect, "rowSelectCallback":rowSelectCallback, "lastColCache":[0,0], "rowHover":rowHover, "colHover":colHover };

                        /*@cc_on
                        @if (@_jscript_version >= 5.7)
                                if(document.compatMode == "BackCompat") fdTableActions.tableCache[table.id].req = true;
                        @else
                                fdTableActions.tableCache[table.id].req = true;
                        @end
                        @*/

                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                fdTableActions.tableCache[table.id].lastRow   = null;
                                fdTableActions.tableCache[table.id].lastCell  = null;
                                fdTableActions.tableCache[table.id].cellHover = cellHover;
                        };
                        /*@end
                        @*/
                        rowArr = [];
                        rowList = table.getElementsByTagName('tr');

                        for(var i = 0;i < rowList.length;i++){
                                colObj = [];
                                elem = rowList[i].firstChild;
                                do {
                                        if(elem.tagName && elem.tagName.toLowerCase().search(/td|th/) != -1) {
                                                colObj[colObj.length] = elem;
                                        };
                                        elem = elem.nextSibling;
                                } while(elem);
                                if(i % 2 == 0 && rowAlt) rowList[i].className = rowList[i].className + " " + rowAlt;
                                rowArr[rowArr.length] = colObj;
                        };

                        /*@cc_on
                        /*@if (@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                if(!cellHover && !rowSelect && !colHover && !rowHover) continue;
                        } else {
                                if(!colHover && !rowSelect) continue;
                        };
                        @else @*/
                        if(!colHover && !rowSelect) continue;
                        /*@end
                        @*/

                        if(rowArr.length > 0){
                                /* Attribution: Parts of the following code based on an original script by Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html) */
                                if(colHover) {
                                        rowLength = rowArr[0].length;
                                        for(var c = 0;c < rowArr[0].length;c++){
                                                if(rowArr[0][c].getAttribute(colspan) > 1){
                                                        rowLength = rowLength + (rowArr[0][c].getAttribute(colspan) - 1);
                                                };
                                        };

                                        workArr  = new Array(rowArr.length);
                                        for(var c = rowArr.length;c--;){
                                                workArr[c]  = new Array(rowLength);
                                        };

                                        colHead = new Array(rowLength);
                                        for(var c = rowLength;c--;){
                                                colHead[c]  = [];
                                        };

                                        for(var c = 0;c < workArr.length;c++) {
                                                celCount = 0;
                                                for(var i = 0;i < rowLength;i++) {
                                                        if(!workArr[c][i]) {
                                                                cel = rowArr[c][celCount];
                                                                colSpan = (cel.getAttribute(colspan) && cel.getAttribute(colspan) > 1) ? cel.getAttribute(colspan) : 1;
                                                                rowSpan = (cel.getAttribute(rowspan) && cel.getAttribute(rowspan) > 1) ? cel.getAttribute(rowspan) : 1;
                                                                cel.className = cel.className + " fdCellProcessed-" + i + "-" + (i + Number(colSpan));
                                                                for(var t = 0;((t < colSpan)&&((i+t) < rowLength));t++){
                                                                        for(var n = 0;((n < rowSpan)&&((c+n) < workArr.length));n++){
                                                                                workArr[(c+n)][(i+t)] = cel;
                                                                        };
                                                                        colHead[(i+t)][colHead[(i+t)].length] = cel;
                                                                };
                                                                if(++celCount == rowArr[c].length) break;
                                                        };
                                                };
                                        };
                                        /* End attribution */
                                        fdTableActions.tableCache[table.id].colCache = colHead;
                                };
                                /*@cc_on
                                /*@if (@_win32)
                                fdTableActions.addEvent(table, "mouseleave",  fdTableActions.tableEvent);
                                @else @*/
                                fdTableActions.addEvent(table, "mouseout",  fdTableActions.tableEvent);
                                /*@end
                                @*/

                                fdTableActions.addEvent(table, "mouseover", fdTableActions.tableEvent);


                                if(rowSelect) {
                                        fdTableActions.addEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                };
        },
        clickEvent:function(e) {
                e = e || window.event;
                var tr, cell;
                if(e.target) tr = e.target;
                else if (e.srcElement) tr = e.srcElement;

                while(true) {
                        if(tr && !cell && tr.nodeName && tr.nodeName.search(/^(TD|TH)$/) != -1) { cell = tr; }
                        else if(tr && tr.nodeName && tr.nodeName.search(/^(TR)$/) != -1) { break; };
                        try { tr = tr.parentNode; } catch(err) { break; };
                };

                if(!tr || !tr.nodeName || tr.nodeName.search(/^(TR)$/) == -1) { return; };

                var remove = (tr.className.search(fdTableActions.tableCache[this.id].rowSelect) != -1);
                var action = true;

                if(fdTableActions.tableCache[this.id].rowSelectCallback) {
                        var func;
                        if(fdTableActions.tableCache[this.id].rowSelectCallback.search(".") != -1) {
                                var split = fdTableActions.tableCache[this.id].rowSelectCallback.split(".");
                                func = window;
                                for(var i = 0, f; f = split[i]; i++) {
                                        if(f in func) {
                                                func = func[f];
                                        } else { break; };
                                };
                        } else if(fdTableActions.tableCache[this.id].rowSelectCallback in window) {
                                func = window[fdTableActions.tableCache[this.id].rowSelectCallback];
                        } else if("rowSelectCallback" in window) {
                                func = window["rowSelectCallback"];
                        };
                        if(typeof func == "function") {
                                action = func({"table":this, "cell":cell, "row":tr, "remove":remove, "rows":fdTableActions.tableCache[this.id].trCache.concat([])});
                        };
                        func = null;
                };

                if(action) {
                        if(remove) {
                                tr.className = tr.className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                var rowArr = [];
                                for(var i = 0, elem; elem = fdTableActions.tableCache[this.id].trCache[i]; i++) {
                                        if(elem != tr) rowArr[rowArr.length] = elem;
                                };
                                fdTableActions.tableCache[this.id].trCache = rowArr;
                        } else {
                                tr.className = tr.className + " " + fdTableActions.tableCache[this.id].rowSelect;
                                if(fdTableActions.tableCache[this.id].rowSelectSingle && fdTableActions.tableCache[this.id].trCache.length) {
                                        fdTableActions.tableCache[this.id].trCache[0].className = fdTableActions.tableCache[this.id].trCache[0].className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                        fdTableActions.tableCache[this.id].trCache = [];
                                };
                                fdTableActions.tableCache[this.id].trCache[fdTableActions.tableCache[this.id].trCache.length] = tr;
                        };
                };
        },
        tableEvent:function(e) {
                e = e || window.event;
                var p;
                if(e.type == "mouseout") {
                        p = e.toElement || e.relatedTarget;
                } else {
                        p = e.target || e.srcElement;
                        if (p.nodeType && p.nodeType == 3) p = p.parentNode;
                };

                while(true) {
                        if(p && p.nodeName && p.nodeName.search(/^(TD|TH)$/) != -1) { break; };
                        try { p = p.parentNode; } catch(err) { break; };
                };

                // Get the old column range
                var colRangeOld = fdTableActions.tableCache[this.id].lastColCache;
                var r = [];
                var n = [];

                if(e.type == "mouseover" && p && p.nodeName.search(/^(TD|TH)$/) != -1) {
                        // Do current cell & row for bloody IE
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].rowHover) {
                                        var tr = p.parentNode;
                                        if(fdTableActions.tableCache[this.id].lastRow != tr) {
                                                if(fdTableActions.tableCache[this.id].lastRow) {
                                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(new RegExp(fdTableActions.tableCache[this.id].rowHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastRow = false;
                                                };
                                                tr.className = tr.className+ " " + fdTableActions.tableCache[this.id].rowHover;
                                                fdTableActions.tableCache[this.id].lastRow = tr;
                                        };
                                };
                                if(fdTableActions.tableCache[this.id].cellHover) {
                                        if(fdTableActions.tableCache[this.id].lastCell != p) {
                                                if(fdTableActions.tableCache[this.id].lastCell) {
                                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(new RegExp(fdTableActions.tableCache[this.id].cellHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastCell = false;
                                                };
                                                p.className = p.className + " " + fdTableActions.tableCache[this.id].cellHover;
                                                fdTableActions.tableCache[this.id].lastCell = p;
                                        };
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover || p.className.search("fdCellProcessed-") == -1) return;
                        var m = p.className.match(/fdCellProcessed-([\d]+)-([\d]+)/);
                        m[1] = Number(m[1]);
                        m[2] = Number(m[2]);
                        if(fdTableActions.tableCache[this.id].lastColCache[0] == m[1] && fdTableActions.tableCache[this.id].lastColCache[1] == m[2]) return;
                        for(var i = colRangeOld[0]; i < colRangeOld[1]; i++) {
                                if(i < m[1] || i >= m[2]) {
                                        r[r.length] = i;
                                };
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [m[1], m[2]];
                        n = [m[1], m[2]];
                } else {
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].lastRow) {
                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(fdTableActions.tableCache[this.id].rowHover,"");
                                        fdTableActions.tableCache[this.id].lastRow = null;
                                };
                                if(fdTableActions.tableCache[this.id].lastCell) {
                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(fdTableActions.tableCache[this.id].cellHover,"");
                                        fdTableActions.tableCache[this.id].lastCell = null;
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover) { return; };
                        for(var i = colRangeOld[0]; i <= colRangeOld[1]; i++) {
                                r[r.length] = i;
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [0,0];
                };

                // Remove
                if(r.length) {
                        for(var i = 0; i < r.length; i++) {
                                if(r[i] >= fdTableActions.tableCache[this.id].colCache.length) continue;
                                elemArr = fdTableActions.tableCache[this.id].colCache[r[i]];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        elem.className = elem.className.replace(fdTableActions.tableCache[this.id].colHover, "");
                                };
                        };
                };

                // Add
                if(n.length) {
                        for(i = n[0]; i < n[1]; i++) {
                                elemArr = fdTableActions.tableCache[this.id].colCache[i];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        if(elem.className.search(fdTableActions.tableCache[this.id].colHover) == -1) {
                                                elem.className = elem.className + " " + fdTableActions.tableCache[this.id].colHover;
                                        };
                                };
                        };
                };
        },
        deselectAllRows:function(tableId) {
                if(!(tableId in fdTableActions.tableCache) || !fdTableActions.tableCache[tableId].rowSelect) return;
                var trList = fdTableActions.tableCache[tableId].trCache;
                for(var i = trList.length; i--;) {
                        trList[i].className = trList[i].className.replace(fdTableActions.tableCache[tableId].rowSelect, "");
                };
                fdTableActions.tableCache[tableId].trCache = [];
                trList = null;
        },
        unLoad:function() {
                var table;
                for(tbl in fdTableActions.tableCache) {
                        table = document.getElementById(tbl);
                        if(table) {
                                fdTableActions.removeEvent(table, "mouseover", fdTableActions.tableEvent);
                                fdTableActions.removeEvent(table, "mouseout",  fdTableActions.tableEvent);
                                if(fdTableActions.tableCache[tbl].rowSelect) {
                                        fdTableActions.removeEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                        /*@cc_on
                        /*@if(@_win32)
                        fdTableActions.tableCache[tbl].req = fdTableActions.tableCache[tbl].lastRow = fdTableActions.tableCache[tbl].lastCell = null;
                        /*@end
                        @*/
                        fdTableActions.tableCache[tbl].colCache = fdTableActions.tableCache[tbl].trCache = null;
                        fdTableActions.tableCache[tbl] = null;
                        delete(fdTableActions.tableCache[tbl]);
                };
        },
        addEvent:function(obj, type, fn) {
                if( obj.attachEvent ) {
                        obj["e"+type+fn] = fn;
                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
                        obj.attachEvent( "on"+type, obj[type+fn] );
                } else {
                        obj.addEventListener( type, fn, true );
                };
        },
        removeEvent: function(obj, type, fn) {
                if( obj.detachEvent ) {
                        try {
                                obj.detachEvent( "on"+type, obj[type+fn] );
                                obj[type+fn] = obj["e"+type+fn] = null;
                        } catch(err) {};
                } else {
                        obj.removeEventListener( type, fn, true );
                };
        }
};

fdTableActions.addEvent(window, "load", fdTableActions.init);
fdTableActions.addEvent(window, "unload", fdTableActions.unLoad);

Revision: 14968
at June 18, 2009 14:53 by beneberle


Updated Code
/* Javascript File  

        Table actions plug-in v0.8 by frequency-decoder.com

        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)

        Please credit frequency decoder in any derivative work - thanks

        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.

        NOTE: Parts of this script is based on a script originally developped by the veritable Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html)

-----------*/

/*
HTML syntax to trigger simple alternate row striping  
    
    <table class="rowstylealt-bluetr".....  

-----------*/

/*
CSS

.bluetr {background:#e8f7ff;}

----------------------------------- */ 


var fdTableActions = {
        tableCache:{},
        init:function() {
                var tables = document.getElementsByTagName("table");
                var rowAlt, colHover, rowHover, rowSelect, rowSelectCallback, cellHover, rowList, rowArr, colObj, elem, rowLength, workArr, celCount, rowSpan, colSpan, cel, colHead, rowL, colL;
                var uniqueID = 0;
                var colspan = "colspan";
                var rowspan = "rowspan";
                /*@cc_on
                /*@if(@_win32)
                colspan = "colSpan";
                rowspan = "rowSpan";
                /*@end
                @*/

                for(var k = 0, table; table = tables[k]; k++) {
                        // Grab the className for the alternate rows
                        rowAlt  = table.className.search(/rowstylealt-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylealt-([\S]+)/)[1];
                        // Highlight columns?
                        colHover  = table.className.search(/colstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/colstylehover-([\S]+)/)[1];
                        // Grab the className for the rowStyleHover
                        rowHover  = table.className.search(/rowstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylehover-([\S]+)/)[1];
                        // Do we select the rows
                        rowSelect = table.className.search(/rowselect-([\S-]+)/) == -1 ? "" : table.className.match(/rowselect-([\S]+)/)[1];
                        // Single or multiple row selection possible
                        rowSelectSingle = table.className.search(/rowselectsingle/) != -1;
                        // Do we have a callback for this table whenever a row is selected?
                        rowSelectCallback = table.className.search(/rowselectcallback-([\S-]+)/) == -1 ? "" : table.className.match(/rowselectcallback-([\S]+)/)[1];
                        // Replace "-" with "." to enable Object.method callbacks
                        rowSelectCallback = rowSelectCallback.replace("-", ".");
                        // Current TH or TD
                        cellHover = table.className.search(/cellhover-([\S-]+)/) == -1 ? "" : table.className.match(/cellhover-([\S]+)/)[1];

                        // Do we even need to continue?
                        if(!(rowAlt || rowHover || colHover || rowSelect || cellHover)) continue;

                        // Create a table ID if necessary
                        if(!table.id) table.id = "fdTable-" + uniqueID++;

                        // Cache this tables details
                        fdTableActions.tableCache[table.id] = { "trCache":[], "rowSelectSingle":rowSelectSingle, "rowSelect":rowSelect, "rowSelectCallback":rowSelectCallback, "lastColCache":[0,0], "rowHover":rowHover, "colHover":colHover };

                        /*@cc_on
                        @if (@_jscript_version >= 5.7)
                                if(document.compatMode == "BackCompat") fdTableActions.tableCache[table.id].req = true;
                        @else
                                fdTableActions.tableCache[table.id].req = true;
                        @end
                        @*/

                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                fdTableActions.tableCache[table.id].lastRow   = null;
                                fdTableActions.tableCache[table.id].lastCell  = null;
                                fdTableActions.tableCache[table.id].cellHover = cellHover;
                        };
                        /*@end
                        @*/
                        rowArr = [];
                        rowList = table.getElementsByTagName('tr');

                        for(var i = 0;i < rowList.length;i++){
                                colObj = [];
                                elem = rowList[i].firstChild;
                                do {
                                        if(elem.tagName && elem.tagName.toLowerCase().search(/td|th/) != -1) {
                                                colObj[colObj.length] = elem;
                                        };
                                        elem = elem.nextSibling;
                                } while(elem);
                                if(i % 2 == 0 && rowAlt) rowList[i].className = rowList[i].className + " " + rowAlt;
                                rowArr[rowArr.length] = colObj;
                        };

                        /*@cc_on
                        /*@if (@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                if(!cellHover && !rowSelect && !colHover && !rowHover) continue;
                        } else {
                                if(!colHover && !rowSelect) continue;
                        };
                        @else @*/
                        if(!colHover && !rowSelect) continue;
                        /*@end
                        @*/

                        if(rowArr.length > 0){
                                /* Attribution: Parts of the following code based on an original script by Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html) */
                                if(colHover) {
                                        rowLength = rowArr[0].length;
                                        for(var c = 0;c < rowArr[0].length;c++){
                                                if(rowArr[0][c].getAttribute(colspan) > 1){
                                                        rowLength = rowLength + (rowArr[0][c].getAttribute(colspan) - 1);
                                                };
                                        };

                                        workArr  = new Array(rowArr.length);
                                        for(var c = rowArr.length;c--;){
                                                workArr[c]  = new Array(rowLength);
                                        };

                                        colHead = new Array(rowLength);
                                        for(var c = rowLength;c--;){
                                                colHead[c]  = [];
                                        };

                                        for(var c = 0;c < workArr.length;c++) {
                                                celCount = 0;
                                                for(var i = 0;i < rowLength;i++) {
                                                        if(!workArr[c][i]) {
                                                                cel = rowArr[c][celCount];
                                                                colSpan = (cel.getAttribute(colspan) && cel.getAttribute(colspan) > 1) ? cel.getAttribute(colspan) : 1;
                                                                rowSpan = (cel.getAttribute(rowspan) && cel.getAttribute(rowspan) > 1) ? cel.getAttribute(rowspan) : 1;
                                                                cel.className = cel.className + " fdCellProcessed-" + i + "-" + (i + Number(colSpan));
                                                                for(var t = 0;((t < colSpan)&&((i+t) < rowLength));t++){
                                                                        for(var n = 0;((n < rowSpan)&&((c+n) < workArr.length));n++){
                                                                                workArr[(c+n)][(i+t)] = cel;
                                                                        };
                                                                        colHead[(i+t)][colHead[(i+t)].length] = cel;
                                                                };
                                                                if(++celCount == rowArr[c].length) break;
                                                        };
                                                };
                                        };
                                        /* End attribution */
                                        fdTableActions.tableCache[table.id].colCache = colHead;
                                };
                                /*@cc_on
                                /*@if (@_win32)
                                fdTableActions.addEvent(table, "mouseleave",  fdTableActions.tableEvent);
                                @else @*/
                                fdTableActions.addEvent(table, "mouseout",  fdTableActions.tableEvent);
                                /*@end
                                @*/

                                fdTableActions.addEvent(table, "mouseover", fdTableActions.tableEvent);


                                if(rowSelect) {
                                        fdTableActions.addEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                };
        },
        clickEvent:function(e) {
                e = e || window.event;
                var tr, cell;
                if(e.target) tr = e.target;
                else if (e.srcElement) tr = e.srcElement;

                while(true) {
                        if(tr && !cell && tr.nodeName && tr.nodeName.search(/^(TD|TH)$/) != -1) { cell = tr; }
                        else if(tr && tr.nodeName && tr.nodeName.search(/^(TR)$/) != -1) { break; };
                        try { tr = tr.parentNode; } catch(err) { break; };
                };

                if(!tr || !tr.nodeName || tr.nodeName.search(/^(TR)$/) == -1) { return; };

                var remove = (tr.className.search(fdTableActions.tableCache[this.id].rowSelect) != -1);
                var action = true;

                if(fdTableActions.tableCache[this.id].rowSelectCallback) {
                        var func;
                        if(fdTableActions.tableCache[this.id].rowSelectCallback.search(".") != -1) {
                                var split = fdTableActions.tableCache[this.id].rowSelectCallback.split(".");
                                func = window;
                                for(var i = 0, f; f = split[i]; i++) {
                                        if(f in func) {
                                                func = func[f];
                                        } else { break; };
                                };
                        } else if(fdTableActions.tableCache[this.id].rowSelectCallback in window) {
                                func = window[fdTableActions.tableCache[this.id].rowSelectCallback];
                        } else if("rowSelectCallback" in window) {
                                func = window["rowSelectCallback"];
                        };
                        if(typeof func == "function") {
                                action = func({"table":this, "cell":cell, "row":tr, "remove":remove, "rows":fdTableActions.tableCache[this.id].trCache.concat([])});
                        };
                        func = null;
                };

                if(action) {
                        if(remove) {
                                tr.className = tr.className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                var rowArr = [];
                                for(var i = 0, elem; elem = fdTableActions.tableCache[this.id].trCache[i]; i++) {
                                        if(elem != tr) rowArr[rowArr.length] = elem;
                                };
                                fdTableActions.tableCache[this.id].trCache = rowArr;
                        } else {
                                tr.className = tr.className + " " + fdTableActions.tableCache[this.id].rowSelect;
                                if(fdTableActions.tableCache[this.id].rowSelectSingle && fdTableActions.tableCache[this.id].trCache.length) {
                                        fdTableActions.tableCache[this.id].trCache[0].className = fdTableActions.tableCache[this.id].trCache[0].className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                        fdTableActions.tableCache[this.id].trCache = [];
                                };
                                fdTableActions.tableCache[this.id].trCache[fdTableActions.tableCache[this.id].trCache.length] = tr;
                        };
                };
        },
        tableEvent:function(e) {
                e = e || window.event;
                var p;
                if(e.type == "mouseout") {
                        p = e.toElement || e.relatedTarget;
                } else {
                        p = e.target || e.srcElement;
                        if (p.nodeType && p.nodeType == 3) p = p.parentNode;
                };

                while(true) {
                        if(p && p.nodeName && p.nodeName.search(/^(TD|TH)$/) != -1) { break; };
                        try { p = p.parentNode; } catch(err) { break; };
                };

                // Get the old column range
                var colRangeOld = fdTableActions.tableCache[this.id].lastColCache;
                var r = [];
                var n = [];

                if(e.type == "mouseover" && p && p.nodeName.search(/^(TD|TH)$/) != -1) {
                        // Do current cell & row for bloody IE
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].rowHover) {
                                        var tr = p.parentNode;
                                        if(fdTableActions.tableCache[this.id].lastRow != tr) {
                                                if(fdTableActions.tableCache[this.id].lastRow) {
                                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(new RegExp(fdTableActions.tableCache[this.id].rowHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastRow = false;
                                                };
                                                tr.className = tr.className+ " " + fdTableActions.tableCache[this.id].rowHover;
                                                fdTableActions.tableCache[this.id].lastRow = tr;
                                        };
                                };
                                if(fdTableActions.tableCache[this.id].cellHover) {
                                        if(fdTableActions.tableCache[this.id].lastCell != p) {
                                                if(fdTableActions.tableCache[this.id].lastCell) {
                                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(new RegExp(fdTableActions.tableCache[this.id].cellHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastCell = false;
                                                };
                                                p.className = p.className + " " + fdTableActions.tableCache[this.id].cellHover;
                                                fdTableActions.tableCache[this.id].lastCell = p;
                                        };
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover || p.className.search("fdCellProcessed-") == -1) return;
                        var m = p.className.match(/fdCellProcessed-([\d]+)-([\d]+)/);
                        m[1] = Number(m[1]);
                        m[2] = Number(m[2]);
                        if(fdTableActions.tableCache[this.id].lastColCache[0] == m[1] && fdTableActions.tableCache[this.id].lastColCache[1] == m[2]) return;
                        for(var i = colRangeOld[0]; i < colRangeOld[1]; i++) {
                                if(i < m[1] || i >= m[2]) {
                                        r[r.length] = i;
                                };
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [m[1], m[2]];
                        n = [m[1], m[2]];
                } else {
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].lastRow) {
                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(fdTableActions.tableCache[this.id].rowHover,"");
                                        fdTableActions.tableCache[this.id].lastRow = null;
                                };
                                if(fdTableActions.tableCache[this.id].lastCell) {
                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(fdTableActions.tableCache[this.id].cellHover,"");
                                        fdTableActions.tableCache[this.id].lastCell = null;
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover) { return; };
                        for(var i = colRangeOld[0]; i <= colRangeOld[1]; i++) {
                                r[r.length] = i;
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [0,0];
                };

                // Remove
                if(r.length) {
                        for(var i = 0; i < r.length; i++) {
                                if(r[i] >= fdTableActions.tableCache[this.id].colCache.length) continue;
                                elemArr = fdTableActions.tableCache[this.id].colCache[r[i]];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        elem.className = elem.className.replace(fdTableActions.tableCache[this.id].colHover, "");
                                };
                        };
                };

                // Add
                if(n.length) {
                        for(i = n[0]; i < n[1]; i++) {
                                elemArr = fdTableActions.tableCache[this.id].colCache[i];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        if(elem.className.search(fdTableActions.tableCache[this.id].colHover) == -1) {
                                                elem.className = elem.className + " " + fdTableActions.tableCache[this.id].colHover;
                                        };
                                };
                        };
                };
        },
        deselectAllRows:function(tableId) {
                if(!(tableId in fdTableActions.tableCache) || !fdTableActions.tableCache[tableId].rowSelect) return;
                var trList = fdTableActions.tableCache[tableId].trCache;
                for(var i = trList.length; i--;) {
                        trList[i].className = trList[i].className.replace(fdTableActions.tableCache[tableId].rowSelect, "");
                };
                fdTableActions.tableCache[tableId].trCache = [];
                trList = null;
        },
        unLoad:function() {
                var table;
                for(tbl in fdTableActions.tableCache) {
                        table = document.getElementById(tbl);
                        if(table) {
                                fdTableActions.removeEvent(table, "mouseover", fdTableActions.tableEvent);
                                fdTableActions.removeEvent(table, "mouseout",  fdTableActions.tableEvent);
                                if(fdTableActions.tableCache[tbl].rowSelect) {
                                        fdTableActions.removeEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                        /*@cc_on
                        /*@if(@_win32)
                        fdTableActions.tableCache[tbl].req = fdTableActions.tableCache[tbl].lastRow = fdTableActions.tableCache[tbl].lastCell = null;
                        /*@end
                        @*/
                        fdTableActions.tableCache[tbl].colCache = fdTableActions.tableCache[tbl].trCache = null;
                        fdTableActions.tableCache[tbl] = null;
                        delete(fdTableActions.tableCache[tbl]);
                };
        },
        addEvent:function(obj, type, fn) {
                if( obj.attachEvent ) {
                        obj["e"+type+fn] = fn;
                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
                        obj.attachEvent( "on"+type, obj[type+fn] );
                } else {
                        obj.addEventListener( type, fn, true );
                };
        },
        removeEvent: function(obj, type, fn) {
                if( obj.detachEvent ) {
                        try {
                                obj.detachEvent( "on"+type, obj[type+fn] );
                                obj[type+fn] = obj["e"+type+fn] = null;
                        } catch(err) {};
                } else {
                        obj.removeEventListener( type, fn, true );
                };
        }
};

fdTableActions.addEvent(window, "load", fdTableActions.init);
fdTableActions.addEvent(window, "unload", fdTableActions.unLoad);

Revision: 14967
at June 18, 2009 14:52 by beneberle


Updated Code
/* Javascript File  */

        Table actions plug-in v0.8 by frequency-decoder.com

        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)

        Please credit frequency decoder in any derivative work - thanks

        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.

        NOTE: Parts of this script is based on a script originally developped by the veritable Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html)

-----------*/

/*
HTML syntax to trigger simple alternate row striping  
    
    <table class="rowstylealt-bluetr".....  

-----------*/

/*
CSS

.bluetr {background:#e8f7ff;}

----------------------------------- */ 


var fdTableActions = {
        tableCache:{},
        init:function() {
                var tables = document.getElementsByTagName("table");
                var rowAlt, colHover, rowHover, rowSelect, rowSelectCallback, cellHover, rowList, rowArr, colObj, elem, rowLength, workArr, celCount, rowSpan, colSpan, cel, colHead, rowL, colL;
                var uniqueID = 0;
                var colspan = "colspan";
                var rowspan = "rowspan";
                /*@cc_on
                /*@if(@_win32)
                colspan = "colSpan";
                rowspan = "rowSpan";
                /*@end
                @*/

                for(var k = 0, table; table = tables[k]; k++) {
                        // Grab the className for the alternate rows
                        rowAlt  = table.className.search(/rowstylealt-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylealt-([\S]+)/)[1];
                        // Highlight columns?
                        colHover  = table.className.search(/colstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/colstylehover-([\S]+)/)[1];
                        // Grab the className for the rowStyleHover
                        rowHover  = table.className.search(/rowstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylehover-([\S]+)/)[1];
                        // Do we select the rows
                        rowSelect = table.className.search(/rowselect-([\S-]+)/) == -1 ? "" : table.className.match(/rowselect-([\S]+)/)[1];
                        // Single or multiple row selection possible
                        rowSelectSingle = table.className.search(/rowselectsingle/) != -1;
                        // Do we have a callback for this table whenever a row is selected?
                        rowSelectCallback = table.className.search(/rowselectcallback-([\S-]+)/) == -1 ? "" : table.className.match(/rowselectcallback-([\S]+)/)[1];
                        // Replace "-" with "." to enable Object.method callbacks
                        rowSelectCallback = rowSelectCallback.replace("-", ".");
                        // Current TH or TD
                        cellHover = table.className.search(/cellhover-([\S-]+)/) == -1 ? "" : table.className.match(/cellhover-([\S]+)/)[1];

                        // Do we even need to continue?
                        if(!(rowAlt || rowHover || colHover || rowSelect || cellHover)) continue;

                        // Create a table ID if necessary
                        if(!table.id) table.id = "fdTable-" + uniqueID++;

                        // Cache this tables details
                        fdTableActions.tableCache[table.id] = { "trCache":[], "rowSelectSingle":rowSelectSingle, "rowSelect":rowSelect, "rowSelectCallback":rowSelectCallback, "lastColCache":[0,0], "rowHover":rowHover, "colHover":colHover };

                        /*@cc_on
                        @if (@_jscript_version >= 5.7)
                                if(document.compatMode == "BackCompat") fdTableActions.tableCache[table.id].req = true;
                        @else
                                fdTableActions.tableCache[table.id].req = true;
                        @end
                        @*/

                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                fdTableActions.tableCache[table.id].lastRow   = null;
                                fdTableActions.tableCache[table.id].lastCell  = null;
                                fdTableActions.tableCache[table.id].cellHover = cellHover;
                        };
                        /*@end
                        @*/
                        rowArr = [];
                        rowList = table.getElementsByTagName('tr');

                        for(var i = 0;i < rowList.length;i++){
                                colObj = [];
                                elem = rowList[i].firstChild;
                                do {
                                        if(elem.tagName && elem.tagName.toLowerCase().search(/td|th/) != -1) {
                                                colObj[colObj.length] = elem;
                                        };
                                        elem = elem.nextSibling;
                                } while(elem);
                                if(i % 2 == 0 && rowAlt) rowList[i].className = rowList[i].className + " " + rowAlt;
                                rowArr[rowArr.length] = colObj;
                        };

                        /*@cc_on
                        /*@if (@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                if(!cellHover && !rowSelect && !colHover && !rowHover) continue;
                        } else {
                                if(!colHover && !rowSelect) continue;
                        };
                        @else @*/
                        if(!colHover && !rowSelect) continue;
                        /*@end
                        @*/

                        if(rowArr.length > 0){
                                /* Attribution: Parts of the following code based on an original script by Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html) */
                                if(colHover) {
                                        rowLength = rowArr[0].length;
                                        for(var c = 0;c < rowArr[0].length;c++){
                                                if(rowArr[0][c].getAttribute(colspan) > 1){
                                                        rowLength = rowLength + (rowArr[0][c].getAttribute(colspan) - 1);
                                                };
                                        };

                                        workArr  = new Array(rowArr.length);
                                        for(var c = rowArr.length;c--;){
                                                workArr[c]  = new Array(rowLength);
                                        };

                                        colHead = new Array(rowLength);
                                        for(var c = rowLength;c--;){
                                                colHead[c]  = [];
                                        };

                                        for(var c = 0;c < workArr.length;c++) {
                                                celCount = 0;
                                                for(var i = 0;i < rowLength;i++) {
                                                        if(!workArr[c][i]) {
                                                                cel = rowArr[c][celCount];
                                                                colSpan = (cel.getAttribute(colspan) && cel.getAttribute(colspan) > 1) ? cel.getAttribute(colspan) : 1;
                                                                rowSpan = (cel.getAttribute(rowspan) && cel.getAttribute(rowspan) > 1) ? cel.getAttribute(rowspan) : 1;
                                                                cel.className = cel.className + " fdCellProcessed-" + i + "-" + (i + Number(colSpan));
                                                                for(var t = 0;((t < colSpan)&&((i+t) < rowLength));t++){
                                                                        for(var n = 0;((n < rowSpan)&&((c+n) < workArr.length));n++){
                                                                                workArr[(c+n)][(i+t)] = cel;
                                                                        };
                                                                        colHead[(i+t)][colHead[(i+t)].length] = cel;
                                                                };
                                                                if(++celCount == rowArr[c].length) break;
                                                        };
                                                };
                                        };
                                        /* End attribution */
                                        fdTableActions.tableCache[table.id].colCache = colHead;
                                };
                                /*@cc_on
                                /*@if (@_win32)
                                fdTableActions.addEvent(table, "mouseleave",  fdTableActions.tableEvent);
                                @else @*/
                                fdTableActions.addEvent(table, "mouseout",  fdTableActions.tableEvent);
                                /*@end
                                @*/

                                fdTableActions.addEvent(table, "mouseover", fdTableActions.tableEvent);


                                if(rowSelect) {
                                        fdTableActions.addEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                };
        },
        clickEvent:function(e) {
                e = e || window.event;
                var tr, cell;
                if(e.target) tr = e.target;
                else if (e.srcElement) tr = e.srcElement;

                while(true) {
                        if(tr && !cell && tr.nodeName && tr.nodeName.search(/^(TD|TH)$/) != -1) { cell = tr; }
                        else if(tr && tr.nodeName && tr.nodeName.search(/^(TR)$/) != -1) { break; };
                        try { tr = tr.parentNode; } catch(err) { break; };
                };

                if(!tr || !tr.nodeName || tr.nodeName.search(/^(TR)$/) == -1) { return; };

                var remove = (tr.className.search(fdTableActions.tableCache[this.id].rowSelect) != -1);
                var action = true;

                if(fdTableActions.tableCache[this.id].rowSelectCallback) {
                        var func;
                        if(fdTableActions.tableCache[this.id].rowSelectCallback.search(".") != -1) {
                                var split = fdTableActions.tableCache[this.id].rowSelectCallback.split(".");
                                func = window;
                                for(var i = 0, f; f = split[i]; i++) {
                                        if(f in func) {
                                                func = func[f];
                                        } else { break; };
                                };
                        } else if(fdTableActions.tableCache[this.id].rowSelectCallback in window) {
                                func = window[fdTableActions.tableCache[this.id].rowSelectCallback];
                        } else if("rowSelectCallback" in window) {
                                func = window["rowSelectCallback"];
                        };
                        if(typeof func == "function") {
                                action = func({"table":this, "cell":cell, "row":tr, "remove":remove, "rows":fdTableActions.tableCache[this.id].trCache.concat([])});
                        };
                        func = null;
                };

                if(action) {
                        if(remove) {
                                tr.className = tr.className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                var rowArr = [];
                                for(var i = 0, elem; elem = fdTableActions.tableCache[this.id].trCache[i]; i++) {
                                        if(elem != tr) rowArr[rowArr.length] = elem;
                                };
                                fdTableActions.tableCache[this.id].trCache = rowArr;
                        } else {
                                tr.className = tr.className + " " + fdTableActions.tableCache[this.id].rowSelect;
                                if(fdTableActions.tableCache[this.id].rowSelectSingle && fdTableActions.tableCache[this.id].trCache.length) {
                                        fdTableActions.tableCache[this.id].trCache[0].className = fdTableActions.tableCache[this.id].trCache[0].className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                        fdTableActions.tableCache[this.id].trCache = [];
                                };
                                fdTableActions.tableCache[this.id].trCache[fdTableActions.tableCache[this.id].trCache.length] = tr;
                        };
                };
        },
        tableEvent:function(e) {
                e = e || window.event;
                var p;
                if(e.type == "mouseout") {
                        p = e.toElement || e.relatedTarget;
                } else {
                        p = e.target || e.srcElement;
                        if (p.nodeType && p.nodeType == 3) p = p.parentNode;
                };

                while(true) {
                        if(p && p.nodeName && p.nodeName.search(/^(TD|TH)$/) != -1) { break; };
                        try { p = p.parentNode; } catch(err) { break; };
                };

                // Get the old column range
                var colRangeOld = fdTableActions.tableCache[this.id].lastColCache;
                var r = [];
                var n = [];

                if(e.type == "mouseover" && p && p.nodeName.search(/^(TD|TH)$/) != -1) {
                        // Do current cell & row for bloody IE
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].rowHover) {
                                        var tr = p.parentNode;
                                        if(fdTableActions.tableCache[this.id].lastRow != tr) {
                                                if(fdTableActions.tableCache[this.id].lastRow) {
                                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(new RegExp(fdTableActions.tableCache[this.id].rowHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastRow = false;
                                                };
                                                tr.className = tr.className+ " " + fdTableActions.tableCache[this.id].rowHover;
                                                fdTableActions.tableCache[this.id].lastRow = tr;
                                        };
                                };
                                if(fdTableActions.tableCache[this.id].cellHover) {
                                        if(fdTableActions.tableCache[this.id].lastCell != p) {
                                                if(fdTableActions.tableCache[this.id].lastCell) {
                                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(new RegExp(fdTableActions.tableCache[this.id].cellHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastCell = false;
                                                };
                                                p.className = p.className + " " + fdTableActions.tableCache[this.id].cellHover;
                                                fdTableActions.tableCache[this.id].lastCell = p;
                                        };
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover || p.className.search("fdCellProcessed-") == -1) return;
                        var m = p.className.match(/fdCellProcessed-([\d]+)-([\d]+)/);
                        m[1] = Number(m[1]);
                        m[2] = Number(m[2]);
                        if(fdTableActions.tableCache[this.id].lastColCache[0] == m[1] && fdTableActions.tableCache[this.id].lastColCache[1] == m[2]) return;
                        for(var i = colRangeOld[0]; i < colRangeOld[1]; i++) {
                                if(i < m[1] || i >= m[2]) {
                                        r[r.length] = i;
                                };
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [m[1], m[2]];
                        n = [m[1], m[2]];
                } else {
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].lastRow) {
                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(fdTableActions.tableCache[this.id].rowHover,"");
                                        fdTableActions.tableCache[this.id].lastRow = null;
                                };
                                if(fdTableActions.tableCache[this.id].lastCell) {
                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(fdTableActions.tableCache[this.id].cellHover,"");
                                        fdTableActions.tableCache[this.id].lastCell = null;
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover) { return; };
                        for(var i = colRangeOld[0]; i <= colRangeOld[1]; i++) {
                                r[r.length] = i;
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [0,0];
                };

                // Remove
                if(r.length) {
                        for(var i = 0; i < r.length; i++) {
                                if(r[i] >= fdTableActions.tableCache[this.id].colCache.length) continue;
                                elemArr = fdTableActions.tableCache[this.id].colCache[r[i]];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        elem.className = elem.className.replace(fdTableActions.tableCache[this.id].colHover, "");
                                };
                        };
                };

                // Add
                if(n.length) {
                        for(i = n[0]; i < n[1]; i++) {
                                elemArr = fdTableActions.tableCache[this.id].colCache[i];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        if(elem.className.search(fdTableActions.tableCache[this.id].colHover) == -1) {
                                                elem.className = elem.className + " " + fdTableActions.tableCache[this.id].colHover;
                                        };
                                };
                        };
                };
        },
        deselectAllRows:function(tableId) {
                if(!(tableId in fdTableActions.tableCache) || !fdTableActions.tableCache[tableId].rowSelect) return;
                var trList = fdTableActions.tableCache[tableId].trCache;
                for(var i = trList.length; i--;) {
                        trList[i].className = trList[i].className.replace(fdTableActions.tableCache[tableId].rowSelect, "");
                };
                fdTableActions.tableCache[tableId].trCache = [];
                trList = null;
        },
        unLoad:function() {
                var table;
                for(tbl in fdTableActions.tableCache) {
                        table = document.getElementById(tbl);
                        if(table) {
                                fdTableActions.removeEvent(table, "mouseover", fdTableActions.tableEvent);
                                fdTableActions.removeEvent(table, "mouseout",  fdTableActions.tableEvent);
                                if(fdTableActions.tableCache[tbl].rowSelect) {
                                        fdTableActions.removeEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                        /*@cc_on
                        /*@if(@_win32)
                        fdTableActions.tableCache[tbl].req = fdTableActions.tableCache[tbl].lastRow = fdTableActions.tableCache[tbl].lastCell = null;
                        /*@end
                        @*/
                        fdTableActions.tableCache[tbl].colCache = fdTableActions.tableCache[tbl].trCache = null;
                        fdTableActions.tableCache[tbl] = null;
                        delete(fdTableActions.tableCache[tbl]);
                };
        },
        addEvent:function(obj, type, fn) {
                if( obj.attachEvent ) {
                        obj["e"+type+fn] = fn;
                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
                        obj.attachEvent( "on"+type, obj[type+fn] );
                } else {
                        obj.addEventListener( type, fn, true );
                };
        },
        removeEvent: function(obj, type, fn) {
                if( obj.detachEvent ) {
                        try {
                                obj.detachEvent( "on"+type, obj[type+fn] );
                                obj[type+fn] = obj["e"+type+fn] = null;
                        } catch(err) {};
                } else {
                        obj.removeEventListener( type, fn, true );
                };
        }
};

fdTableActions.addEvent(window, "load", fdTableActions.init);
fdTableActions.addEvent(window, "unload", fdTableActions.unLoad);

Revision: 14966
at June 18, 2009 14:39 by beneberle


Initial Code
/* Javascript File  */
        Table actions plug-in v0.8 by frequency-decoder.com

        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)

        Please credit frequency decoder in any derivative work - thanks

        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.

        NOTE: Parts of this script is based on a script originally developped by the veritable Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html)
*/

var fdTableActions = {
        tableCache:{},
        init:function() {
                var tables = document.getElementsByTagName("table");
                var rowAlt, colHover, rowHover, rowSelect, rowSelectCallback, cellHover, rowList, rowArr, colObj, elem, rowLength, workArr, celCount, rowSpan, colSpan, cel, colHead, rowL, colL;
                var uniqueID = 0;
                var colspan = "colspan";
                var rowspan = "rowspan";
                /*@cc_on
                /*@if(@_win32)
                colspan = "colSpan";
                rowspan = "rowSpan";
                /*@end
                @*/

                for(var k = 0, table; table = tables[k]; k++) {
                        // Grab the className for the alternate rows
                        rowAlt  = table.className.search(/rowstylealt-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylealt-([\S]+)/)[1];
                        // Highlight columns?
                        colHover  = table.className.search(/colstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/colstylehover-([\S]+)/)[1];
                        // Grab the className for the rowStyleHover
                        rowHover  = table.className.search(/rowstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylehover-([\S]+)/)[1];
                        // Do we select the rows
                        rowSelect = table.className.search(/rowselect-([\S-]+)/) == -1 ? "" : table.className.match(/rowselect-([\S]+)/)[1];
                        // Single or multiple row selection possible
                        rowSelectSingle = table.className.search(/rowselectsingle/) != -1;
                        // Do we have a callback for this table whenever a row is selected?
                        rowSelectCallback = table.className.search(/rowselectcallback-([\S-]+)/) == -1 ? "" : table.className.match(/rowselectcallback-([\S]+)/)[1];
                        // Replace "-" with "." to enable Object.method callbacks
                        rowSelectCallback = rowSelectCallback.replace("-", ".");
                        // Current TH or TD
                        cellHover = table.className.search(/cellhover-([\S-]+)/) == -1 ? "" : table.className.match(/cellhover-([\S]+)/)[1];

                        // Do we even need to continue?
                        if(!(rowAlt || rowHover || colHover || rowSelect || cellHover)) continue;

                        // Create a table ID if necessary
                        if(!table.id) table.id = "fdTable-" + uniqueID++;

                        // Cache this tables details
                        fdTableActions.tableCache[table.id] = { "trCache":[], "rowSelectSingle":rowSelectSingle, "rowSelect":rowSelect, "rowSelectCallback":rowSelectCallback, "lastColCache":[0,0], "rowHover":rowHover, "colHover":colHover };

                        /*@cc_on
                        @if (@_jscript_version >= 5.7)
                                if(document.compatMode == "BackCompat") fdTableActions.tableCache[table.id].req = true;
                        @else
                                fdTableActions.tableCache[table.id].req = true;
                        @end
                        @*/

                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                fdTableActions.tableCache[table.id].lastRow   = null;
                                fdTableActions.tableCache[table.id].lastCell  = null;
                                fdTableActions.tableCache[table.id].cellHover = cellHover;
                        };
                        /*@end
                        @*/
                        rowArr = [];
                        rowList = table.getElementsByTagName('tr');

                        for(var i = 0;i < rowList.length;i++){
                                colObj = [];
                                elem = rowList[i].firstChild;
                                do {
                                        if(elem.tagName && elem.tagName.toLowerCase().search(/td|th/) != -1) {
                                                colObj[colObj.length] = elem;
                                        };
                                        elem = elem.nextSibling;
                                } while(elem);
                                if(i % 2 == 0 && rowAlt) rowList[i].className = rowList[i].className + " " + rowAlt;
                                rowArr[rowArr.length] = colObj;
                        };

                        /*@cc_on
                        /*@if (@_win32)
                        if(fdTableActions.tableCache[table.id].req) {
                                if(!cellHover && !rowSelect && !colHover && !rowHover) continue;
                        } else {
                                if(!colHover && !rowSelect) continue;
                        };
                        @else @*/
                        if(!colHover && !rowSelect) continue;
                        /*@end
                        @*/

                        if(rowArr.length > 0){
                                /* Attribution: Parts of the following code based on an original script by Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html) */
                                if(colHover) {
                                        rowLength = rowArr[0].length;
                                        for(var c = 0;c < rowArr[0].length;c++){
                                                if(rowArr[0][c].getAttribute(colspan) > 1){
                                                        rowLength = rowLength + (rowArr[0][c].getAttribute(colspan) - 1);
                                                };
                                        };

                                        workArr  = new Array(rowArr.length);
                                        for(var c = rowArr.length;c--;){
                                                workArr[c]  = new Array(rowLength);
                                        };

                                        colHead = new Array(rowLength);
                                        for(var c = rowLength;c--;){
                                                colHead[c]  = [];
                                        };

                                        for(var c = 0;c < workArr.length;c++) {
                                                celCount = 0;
                                                for(var i = 0;i < rowLength;i++) {
                                                        if(!workArr[c][i]) {
                                                                cel = rowArr[c][celCount];
                                                                colSpan = (cel.getAttribute(colspan) && cel.getAttribute(colspan) > 1) ? cel.getAttribute(colspan) : 1;
                                                                rowSpan = (cel.getAttribute(rowspan) && cel.getAttribute(rowspan) > 1) ? cel.getAttribute(rowspan) : 1;
                                                                cel.className = cel.className + " fdCellProcessed-" + i + "-" + (i + Number(colSpan));
                                                                for(var t = 0;((t < colSpan)&&((i+t) < rowLength));t++){
                                                                        for(var n = 0;((n < rowSpan)&&((c+n) < workArr.length));n++){
                                                                                workArr[(c+n)][(i+t)] = cel;
                                                                        };
                                                                        colHead[(i+t)][colHead[(i+t)].length] = cel;
                                                                };
                                                                if(++celCount == rowArr[c].length) break;
                                                        };
                                                };
                                        };
                                        /* End attribution */
                                        fdTableActions.tableCache[table.id].colCache = colHead;
                                };
                                /*@cc_on
                                /*@if (@_win32)
                                fdTableActions.addEvent(table, "mouseleave",  fdTableActions.tableEvent);
                                @else @*/
                                fdTableActions.addEvent(table, "mouseout",  fdTableActions.tableEvent);
                                /*@end
                                @*/

                                fdTableActions.addEvent(table, "mouseover", fdTableActions.tableEvent);


                                if(rowSelect) {
                                        fdTableActions.addEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                };
        },
        clickEvent:function(e) {
                e = e || window.event;
                var tr, cell;
                if(e.target) tr = e.target;
                else if (e.srcElement) tr = e.srcElement;

                while(true) {
                        if(tr && !cell && tr.nodeName && tr.nodeName.search(/^(TD|TH)$/) != -1) { cell = tr; }
                        else if(tr && tr.nodeName && tr.nodeName.search(/^(TR)$/) != -1) { break; };
                        try { tr = tr.parentNode; } catch(err) { break; };
                };

                if(!tr || !tr.nodeName || tr.nodeName.search(/^(TR)$/) == -1) { return; };

                var remove = (tr.className.search(fdTableActions.tableCache[this.id].rowSelect) != -1);
                var action = true;

                if(fdTableActions.tableCache[this.id].rowSelectCallback) {
                        var func;
                        if(fdTableActions.tableCache[this.id].rowSelectCallback.search(".") != -1) {
                                var split = fdTableActions.tableCache[this.id].rowSelectCallback.split(".");
                                func = window;
                                for(var i = 0, f; f = split[i]; i++) {
                                        if(f in func) {
                                                func = func[f];
                                        } else { break; };
                                };
                        } else if(fdTableActions.tableCache[this.id].rowSelectCallback in window) {
                                func = window[fdTableActions.tableCache[this.id].rowSelectCallback];
                        } else if("rowSelectCallback" in window) {
                                func = window["rowSelectCallback"];
                        };
                        if(typeof func == "function") {
                                action = func({"table":this, "cell":cell, "row":tr, "remove":remove, "rows":fdTableActions.tableCache[this.id].trCache.concat([])});
                        };
                        func = null;
                };

                if(action) {
                        if(remove) {
                                tr.className = tr.className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                var rowArr = [];
                                for(var i = 0, elem; elem = fdTableActions.tableCache[this.id].trCache[i]; i++) {
                                        if(elem != tr) rowArr[rowArr.length] = elem;
                                };
                                fdTableActions.tableCache[this.id].trCache = rowArr;
                        } else {
                                tr.className = tr.className + " " + fdTableActions.tableCache[this.id].rowSelect;
                                if(fdTableActions.tableCache[this.id].rowSelectSingle && fdTableActions.tableCache[this.id].trCache.length) {
                                        fdTableActions.tableCache[this.id].trCache[0].className = fdTableActions.tableCache[this.id].trCache[0].className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
                                        fdTableActions.tableCache[this.id].trCache = [];
                                };
                                fdTableActions.tableCache[this.id].trCache[fdTableActions.tableCache[this.id].trCache.length] = tr;
                        };
                };
        },
        tableEvent:function(e) {
                e = e || window.event;
                var p;
                if(e.type == "mouseout") {
                        p = e.toElement || e.relatedTarget;
                } else {
                        p = e.target || e.srcElement;
                        if (p.nodeType && p.nodeType == 3) p = p.parentNode;
                };

                while(true) {
                        if(p && p.nodeName && p.nodeName.search(/^(TD|TH)$/) != -1) { break; };
                        try { p = p.parentNode; } catch(err) { break; };
                };

                // Get the old column range
                var colRangeOld = fdTableActions.tableCache[this.id].lastColCache;
                var r = [];
                var n = [];

                if(e.type == "mouseover" && p && p.nodeName.search(/^(TD|TH)$/) != -1) {
                        // Do current cell & row for bloody IE
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].rowHover) {
                                        var tr = p.parentNode;
                                        if(fdTableActions.tableCache[this.id].lastRow != tr) {
                                                if(fdTableActions.tableCache[this.id].lastRow) {
                                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(new RegExp(fdTableActions.tableCache[this.id].rowHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastRow = false;
                                                };
                                                tr.className = tr.className+ " " + fdTableActions.tableCache[this.id].rowHover;
                                                fdTableActions.tableCache[this.id].lastRow = tr;
                                        };
                                };
                                if(fdTableActions.tableCache[this.id].cellHover) {
                                        if(fdTableActions.tableCache[this.id].lastCell != p) {
                                                if(fdTableActions.tableCache[this.id].lastCell) {
                                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(new RegExp(fdTableActions.tableCache[this.id].cellHover, "g"),"");
                                                        fdTableActions.tableCache[this.id].lastCell = false;
                                                };
                                                p.className = p.className + " " + fdTableActions.tableCache[this.id].cellHover;
                                                fdTableActions.tableCache[this.id].lastCell = p;
                                        };
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover || p.className.search("fdCellProcessed-") == -1) return;
                        var m = p.className.match(/fdCellProcessed-([\d]+)-([\d]+)/);
                        m[1] = Number(m[1]);
                        m[2] = Number(m[2]);
                        if(fdTableActions.tableCache[this.id].lastColCache[0] == m[1] && fdTableActions.tableCache[this.id].lastColCache[1] == m[2]) return;
                        for(var i = colRangeOld[0]; i < colRangeOld[1]; i++) {
                                if(i < m[1] || i >= m[2]) {
                                        r[r.length] = i;
                                };
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [m[1], m[2]];
                        n = [m[1], m[2]];
                } else {
                        /*@cc_on
                        /*@if(@_win32)
                        if(fdTableActions.tableCache[this.id].req) {
                                if(fdTableActions.tableCache[this.id].lastRow) {
                                        fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(fdTableActions.tableCache[this.id].rowHover,"");
                                        fdTableActions.tableCache[this.id].lastRow = null;
                                };
                                if(fdTableActions.tableCache[this.id].lastCell) {
                                        fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(fdTableActions.tableCache[this.id].cellHover,"");
                                        fdTableActions.tableCache[this.id].lastCell = null;
                                };
                        };
                        /*@end
                        @*/
                        if(!fdTableActions.tableCache[this.id].colHover) { return; };
                        for(var i = colRangeOld[0]; i <= colRangeOld[1]; i++) {
                                r[r.length] = i;
                        };
                        fdTableActions.tableCache[this.id].lastColCache = [0,0];
                };

                // Remove
                if(r.length) {
                        for(var i = 0; i < r.length; i++) {
                                if(r[i] >= fdTableActions.tableCache[this.id].colCache.length) continue;
                                elemArr = fdTableActions.tableCache[this.id].colCache[r[i]];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        elem.className = elem.className.replace(fdTableActions.tableCache[this.id].colHover, "");
                                };
                        };
                };

                // Add
                if(n.length) {
                        for(i = n[0]; i < n[1]; i++) {
                                elemArr = fdTableActions.tableCache[this.id].colCache[i];
                                for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
                                        if(elem.className.search(fdTableActions.tableCache[this.id].colHover) == -1) {
                                                elem.className = elem.className + " " + fdTableActions.tableCache[this.id].colHover;
                                        };
                                };
                        };
                };
        },
        deselectAllRows:function(tableId) {
                if(!(tableId in fdTableActions.tableCache) || !fdTableActions.tableCache[tableId].rowSelect) return;
                var trList = fdTableActions.tableCache[tableId].trCache;
                for(var i = trList.length; i--;) {
                        trList[i].className = trList[i].className.replace(fdTableActions.tableCache[tableId].rowSelect, "");
                };
                fdTableActions.tableCache[tableId].trCache = [];
                trList = null;
        },
        unLoad:function() {
                var table;
                for(tbl in fdTableActions.tableCache) {
                        table = document.getElementById(tbl);
                        if(table) {
                                fdTableActions.removeEvent(table, "mouseover", fdTableActions.tableEvent);
                                fdTableActions.removeEvent(table, "mouseout",  fdTableActions.tableEvent);
                                if(fdTableActions.tableCache[tbl].rowSelect) {
                                        fdTableActions.removeEvent(table, "click",  fdTableActions.clickEvent);
                                };
                        };
                        /*@cc_on
                        /*@if(@_win32)
                        fdTableActions.tableCache[tbl].req = fdTableActions.tableCache[tbl].lastRow = fdTableActions.tableCache[tbl].lastCell = null;
                        /*@end
                        @*/
                        fdTableActions.tableCache[tbl].colCache = fdTableActions.tableCache[tbl].trCache = null;
                        fdTableActions.tableCache[tbl] = null;
                        delete(fdTableActions.tableCache[tbl]);
                };
        },
        addEvent:function(obj, type, fn) {
                if( obj.attachEvent ) {
                        obj["e"+type+fn] = fn;
                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
                        obj.attachEvent( "on"+type, obj[type+fn] );
                } else {
                        obj.addEventListener( type, fn, true );
                };
        },
        removeEvent: function(obj, type, fn) {
                if( obj.detachEvent ) {
                        try {
                                obj.detachEvent( "on"+type, obj[type+fn] );
                                obj[type+fn] = obj["e"+type+fn] = null;
                        } catch(err) {};
                } else {
                        obj.removeEventListener( type, fn, true );
                };
        }
};

fdTableActions.addEvent(window, "load", fdTableActions.init);
fdTableActions.addEvent(window, "unload", fdTableActions.unLoad);

Initial URL
http://www.frequency-decoder.com/2007/11/15/unobtrusive-table-actions-script

Initial Description
- a javascript for alternate row/column table striping
- supports row hover, column hover and cell hover effects and click events.
demo here:
http://www.frequency-decoder.com/demo/table-actions/

Initial Title
Table actions plug-in v0.8 by frequency-decoder.com

Initial Tags
javascript, html

Initial Language
JavaScript