Upgrade column management with possibility to return to the initial columns. Little debug in all tag list.
/*
* jQuery columnManager plugin
* Version: 0.2.5
*
* Copyright (c) 2007 Roman Weich
* http://p.sohei.org
*
* Dual licensed under the MIT and GPL licenses
* (This means that you can choose the license that best suits your project, and use it accordingly):
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Changelog:
* v 0.2.5 - 2008-01-17
* -change: added options "show" and "hide". with these functions the user can control the way to show or hide the cells
* -change: added $.fn.showColumns() and $.fn.hideColumns which allows to explicitely show or hide any given number of columns
* v 0.2.4 - 2007-12-02
* -fix: a problem with the on/off css classes when manually toggling columns which were not in the column header list
* -fix: an error in the createColumnHeaderList function incorectly resetting the visibility state of the columns
* -change: restructured some of the code
* v 0.2.3 - 2007-12-02
* -change: when a column header has no text but some html markup as content, the markup is used in the column header list instead of "undefined"
* v 0.2.2 - 2007-11-27
* -change: added the ablity to change the on and off CSS classes in the column header list through $().toggleColumns()
* -change: to avoid conflicts with other plugins, the table-referencing data in the column header list is now stored as an expando and not in the class name as before
* v 0.2.1 - 2007-08-14
* -fix: handling of colspans didn't work properly for the very first spanning column
* -change: altered the cookie handling routines for easier management
* v 0.2.0 - 2007-04-14
* -change: supports tables with colspanned and rowspanned cells now
* v 0.1.4 - 2007-04-11
* -change: added onToggle option to specify a custom callback function for the toggling over the column header list
* v 0.1.3 - 2007-04-05
* -fix: bug when saving the value in a cookie
* -change: toggleColumns takes a number or an array of numbers as argument now
* v 0.1.2 - 2007-04-02
* -change: added jsDoc style documentation and examples
* -change: the column index passed to toggleColumns() starts at 1 now (conforming to the values passed in the hideInList and colsHidden options)
* v 0.1.1 - 2007-03-30
* -change: changed hideInList and colsHidden options to hold integer values for the column indexes to be affected
* -change: made the toggleColumns function accessible through the jquery object, to toggle the state without the need for the column header list
* -fix: error when not finding the passed listTargetID in the dom
* v 0.1.0 - 2007-03-27
*/
(function($)
{
var defaults = {
listTargetID : null,
onClass : '',
offClass : '',
hideInList: [],
colsHidden: [],
saveState: false,
onToggle: null,
show: function(cell){
showCell(cell);
},
hide: function(cell){
hideCell(cell);
}
};
var idCount = 0;
var cookieName = 'columnManagerC';
/**
* Saves the current state for the table in a cookie.
* @param {element} table The table for which to save the current state.
*/
var saveCurrentValue = function(table)
{
var val = '', i = 0, colsVisible = table.cMColsVisible;
if ( table.cMSaveState && table.id && colsVisible && $.cookie )
{
for ( ; i < colsVisible.length; i++ )
{
val += ( colsVisible[i] == false ) ? 0 : 1;
}
$.cookie(cookieName + table.id, val, {expires: 9999});
}
};
/**
* Hides a cell.
* It rewrites itself after the browsercheck!
* @param {element} cell The cell to hide.
*/
var hideCell = function(cell)
{
if ( jQuery.browser.msie )
{
(hideCell = function(c)
{
c.style.setAttribute('display', 'none');
})(cell);
}
else
{
(hideCell = function(c)
{
c.style.display = 'none';
})(cell);
}
};
/**
* Makes a cell visible again.
* It rewrites itself after the browsercheck!
* @param {element} cell The cell to show.
*/
var showCell = function(cell)
{
if ( jQuery.browser.msie )
{
(showCell = function(c)
{
c.style.setAttribute('display', 'block');
})(cell);
}
else
{
(showCell = function(c)
{
c.style.display = 'table-cell';
})(cell);
}
};
/**
* Returns the visible state of a cell.
* It rewrites itself after the browsercheck!
* @param {element} cell The cell to test.
*/
var cellVisible = function(cell)
{
if ( jQuery.browser.msie )
{
return (cellVisible = function(c)
{
return c.style.getAttribute('display') != 'none';
})(cell);
}
else
{
return (cellVisible = function(c)
{
return c.style.display != 'none';
})(cell);
}
};
/**
* Returns the cell element which has the passed column index value.
* @param {element} table The table element.
* @param {array} cells The cells to loop through.
* @param {integer} col The column index to look for.
*/
var getCell = function(table, cells, col)
{
for ( var i = 0; i < cells.length; i++ )
{
if ( cells[i].realIndex === undefined ) //the test is here, because rows/cells could get added after the first run
{
fixCellIndexes(table);
}
if ( cells[i].realIndex == col )
{
return cells[i];
}
}
return null;
};
/**
* Calculates the actual cellIndex value of all cells in the table and stores it in the realCell property of each cell.
* Thats done because the cellIndex value isn't correct when colspans or rowspans are used.
* Originally created by Matt Kruse for his table library - Big Thanks! (see http://www.javascripttoolbox.com/)
* @param {element} table The table element.
*/
var fixCellIndexes = function(table)
{
var rows = table.rows;
var len = rows.length;
var matrix = [];
for ( var i = 0; i < len; i++ )
{
var cells = rows[i].cells;
var clen = cells.length;
for ( var j = 0; j < clen; j++ )
{
var c = cells[j];
var rowSpan = c.rowSpan || 1;
var colSpan = c.colSpan || 1;
var firstAvailCol = -1;
if ( !matrix[i] )
{
matrix[i] = [];
}
var m = matrix[i];
// Find first available column in the first row
while ( m[++firstAvailCol] ) {}
c.realIndex = firstAvailCol;
for ( var k = i; k < i + rowSpan; k++ )
{
if ( !matrix[k] )
{
matrix[k] = [];
}
var matrixrow = matrix[k];
for ( var l = firstAvailCol; l < firstAvailCol + colSpan; l++ )
{
matrixrow[l] = 1;
}
}
}
}
};
/**
* Manages the column display state for a table.
*
* Features:
* Saves the state and recreates it on the next visit of the site (requires cookie-plugin).
* Extracts all headers and builds an unordered(<UL>) list out of them, where clicking an list element will show/hide the matching column.
*
* @param {map} options An object for optional settings (options described below).
*
* @option {string} listTargetID The ID attribute of the element the column header list will be added to.
* Default value: null
* @option {string} onClass A CSS class that is used on the items in the column header list, for which the column state is visible
* Works only with listTargetID set!
* Default value: ''
* @option {string} offClass A CSS class that is used on the items in the column header list, for which the column state is hidden.
* Works only with listTargetID set!
* Default value: ''
* @option {array} hideInList An array of numbers. Each column with the matching column index won't be displayed in the column header list.
* Index starting at 1!
* Default value: [] (all columns will be included in the list)
* @option {array} colsHidden An array of numbers. Each column with the matching column index will get hidden by default.
* The value is overwritten when saveState is true and a cookie is set for this table.
* Index starting at 1!
* Default value: []
* @option {boolean} saveState Save a cookie with the sate information of each column.
* Requires jQuery cookie plugin.
* Default value: false
* @option {function} onToggle Callback function which is triggered when the visibility state of a column was toggled through the column header list.
* The passed parameters are: the column index(integer) and the visibility state(boolean).
* Default value: null
*
* @option {function} show Function which is called to show a table cell.
* The passed parameters are: the table cell (DOM-element).
* Default value: a functions which simply sets the display-style to block (visible)
*
* @option {function} hide Function which is called to hide a table cell.
* The passed parameters are: the table cell (DOM-element).
* Default value: a functions which simply sets the display-style to none (invisible)
*
* @example $('#table').columnManager([listTargetID: "target", onClass: "on", offClass: "off"]);
* @desc Creates the column header list in the element with the ID attribute "target" and sets the CSS classes for the visible("on") and hidden("off") states.
*
* @example $('#table').columnManager([listTargetID: "target", hideInList: [1, 4]]);
* @desc Creates the column header list in the element with the ID attribute "target" but without the first and fourth column.
*
* @example $('#table').columnManager([listTargetID: "target", colsHidden: [1, 4]]);
* @desc Creates the column header list in the element with the ID attribute "target" and hides the first and fourth column by default.
*
* @example $('#table').columnManager([saveState: true]);
* @desc Enables the saving of visibility informations for the columns. Does not create a column header list! Toggle the columns visiblity through $('selector').toggleColumns().
*
* @type jQuery
*
* @name columnManager
* @cat Plugins/columnManager
* @author Roman Weich (http://p.sohei.org)
*/
$.fn.columnManager = function(options)
{
var settings = $.extend({}, defaults, options);
/**
* Creates the column header list.
* @param {element} table The table element for which to create the list.
*/
var createColumnHeaderList = function(table)
{
if ( !settings.listTargetID )
{
return;
}
var $target = $('#' + settings.listTargetID);
if ( !$target.length )
{
return;
}
//select headrow - when there is no thead-element, use the first row in the table
var headRow = null;
if ( table.tHead && table.tHead.length )
{
headRow = table.tHead.rows[0];
}
else if ( table.rows.length )
{
headRow = table.rows[0];
}
else
{
return; //no header - nothing to do
}
var cells = headRow.cells;
if ( !cells.length )
{
return; //no header - nothing to do
}
//create list in target element
var $list = null;
if ( $target.get(0).nodeName.toUpperCase() == 'UL' )
{
$list = $target;
}
else
{
$list = $('<ul></ul>');
$target.append($list);
}
var colsVisible = table.cMColsVisible;
//create list elements from headers
for ( var i = 0; i < cells.length; i++ )
{
if ( $.inArray(i + 1, settings.hideInList) >= 0 )
{
continue;
}
colsVisible[i] = ( colsVisible[i] !== undefined ) ? colsVisible[i] : true;
var text = $(cells[i]).text(),
addClass;
if ( !text.length )
{
text = $(cells[i]).html();
if ( !text.length ) //still nothing?
{
text = 'undefined';
}
}
if ( colsVisible[i] && settings.onClass )
{
addClass = settings.onClass;
}
else if ( !colsVisible[i] && settings.offClass )
{
addClass = settings.offClass;
}
var $li = $('<li class="' + addClass + '">' + text + '</li>').click(toggleClick);
$li[0].cmData = {id: table.id, col: i};
$list.append($li);
}
// START modifications IRI
$list.append('<li class="">----------</li>');
var $li = $('<li class="wikitag_reinit">Colonnes initiales</li>').click(toggleClick);
$li[0].cmData = {id: table.id, col: "reinit"};
$list.append($li);
// END modifications IRI
table.cMColsVisible = colsVisible;
};
/**
* called when an item in the column header list is clicked
*/
var toggleClick = function()
{
//get table id and column name
var data = this.cmData;
if ( data && data.id && (data.col >= 0 || data.col=="reinit") )
{
// START modifications IRI
if(data.col=="reinit"){
// BE CAREFUL : the var columsToHide needs to be defined. It is usually because columsToHide is often needed at columnManager initialisation.
var $table = $('#' + data.id);
var opt = {listTargetID:settings.listTargetID, onClass:settings.onClass, offClass:settings.offClass};
if($table){
$table.showColumns(null, opt);
if(columsToHide){
$table.hideColumns(columsToHide, opt);
}
}
}
else{
// END modifications IRI
var colNum = data.col,
$table = $('#' + data.id);
if ( $table.length )
{
$table.toggleColumns([colNum + 1], settings);
//set the appropriate classes to the column header list
var colsVisible = $table.get(0).cMColsVisible;
if ( settings.onToggle )
{
settings.onToggle.apply($table.get(0), [colNum + 1, colsVisible[colNum]]);
}
}
}
}
};
/**
* Reads the saved state from the cookie.
* @param {string} tableID The ID attribute from the table.
*/
var getSavedValue = function(tableID)
{
var val = $.cookie(cookieName + tableID);
if ( val )
{
var ar = val.split('');
for ( var i = 0; i < ar.length; i++ )
{
ar[i] &= 1;
}
return ar;
}
return false;
};
return this.each(function()
{
this.id = this.id || 'jQcM0O' + idCount++; //we need an id for the column header list stuff
var i,
colsHide = [],
colsVisible = [];
//fix cellIndex values
fixCellIndexes(this);
//some columns hidden by default?
if ( settings.colsHidden.length )
{
for ( i = 0; i < settings.colsHidden.length; i++ )
{
colsVisible[settings.colsHidden[i] - 1] = true;
colsHide[settings.colsHidden[i] - 1] = true;
}
}
//get saved state - and overwrite defaults
if ( settings.saveState )
{
var colsSaved = getSavedValue(this.id);
if ( colsSaved && colsSaved.length )
{
for ( i = 0; i < colsSaved.length; i++ )
{
colsVisible[i] = true;
colsHide[i] = !colsSaved[i];
}
}
this.cMSaveState = true;
}
//assign initial colsVisible var to the table (needed for toggling and saving the state)
this.cMColsVisible = colsVisible;
//something to hide already?
if ( colsHide.length )
{
var a = [];
for ( i = 0; i < colsHide.length; i++ )
{
if ( colsHide[i] )
{
a[a.length] = i + 1;
}
}
if ( a.length )
{
$(this).toggleColumns(a);
}
}
//create column header list
createColumnHeaderList(this);
});
};
/**
* Shows or hides table columns.
*
* @param {integer|array} columns A number or an array of numbers. The display state(visible/hidden) for each column with the matching column index will get toggled.
* Column index starts at 1! (see the example)
*
* @param {map} options An object for optional settings to handle the on and off CSS classes in the column header list (options described below).
* @option {string} listTargetID The ID attribute of the element with the column header.
* @option {string} onClass A CSS class that is used on the items in the column header list, for which the column state is visible
* @option {string} offClass A CSS class that is used on the items in the column header list, for which the column state is hidden.
* @option {function} show Function which is called to show a table cell.
* @option {function} hide Function which is called to hide a table cell.
*
* @example $('#table').toggleColumns([2, 4], {hide: function(cell) { $(cell).fadeOut("slow"); }});
* @before <table id="table">
* <thead>
* <th>one</th
* <th>two</th
* <th>three</th
* <th>four</th
* </thead>
* </table>
* @desc Toggles the visible state for the columns "two" and "four". Use custom function to fade the cell out when hiding it.
*
* @example $('#table').toggleColumns(3, {listTargetID: 'theID', onClass: 'vis'});
* @before <table id="table">
* <thead>
* <th>one</th
* <th>two</th
* <th>three</th
* <th>four</th
* </thead>
* </table>
* @desc Toggles the visible state for column "three" and sets or removes the CSS class 'vis' to the appropriate column header according to the visibility of the column.
*
* @type jQuery
*
* @name toggleColumns
* @cat Plugins/columnManager
* @author Roman Weich (http://p.sohei.org)
*/
$.fn.toggleColumns = function(columns, cmo)
{
return this.each(function()
{
var i, toggle, di,
rows = this.rows,
colsVisible = this.cMColsVisible;
if ( !columns )
return;
if ( columns.constructor == Number )
columns = [columns];
if ( !colsVisible )
colsVisible = this.cMColsVisible = [];
//go through all rows in the table and hide the cells
for ( i = 0; i < rows.length; i++ )
{
var cells = rows[i].cells;
for ( var k = 0; k < columns.length; k++ )
{
var col = columns[k] - 1;
if ( col >= 0 )
{
//find the cell with the correct index
var c = getCell(this, cells, col);
//cell not found - maybe a previous one has a colspan? - search it!
if ( !c )
{
var cco = col;
while ( cco > 0 && !(c = getCell(this, cells, --cco)) ) {} //find the previous cell
if ( !c )
{
continue;
}
}
//set toggle direction
if ( colsVisible[col] == undefined )//not initialized yet
{
colsVisible[col] = true;
}
if ( colsVisible[col] )
{
toggle = cmo && cmo.hide ? cmo.hide : hideCell;
di = -1;
}
else
{
toggle = cmo && cmo.show ? cmo.show : showCell;
di = 1;
}
if ( !c.chSpan )
{
c.chSpan = 0;
}
//the cell has a colspan - so dont show/hide - just change the colspan
if ( c.colSpan > 1 || (di == 1 && c.chSpan && cellVisible(c)) )
{
//is the colspan even reaching this cell? if not we have a rowspan -> nothing to do
if ( c.realIndex + c.colSpan + c.chSpan - 1 < col )
{
continue;
}
c.colSpan += di;
c.chSpan += di * -1;
}
else if ( c.realIndex + c.chSpan < col )//a previous cell was found, but doesn't affect this one (rowspan)
{
continue;
}
else //toggle cell
{
toggle(c);
}
}
}
}
//set the colsVisible var
for ( i = 0; i < columns.length; i++ )
{
this.cMColsVisible[columns[i] - 1] = !colsVisible[columns[i] - 1];
//set the appropriate classes to the column header list, if the options have been passed
if ( cmo && cmo.listTargetID && ( cmo.onClass || cmo.offClass ) )
{
var onC = cmo.onClass, offC = cmo.offClass, $li;
if ( colsVisible[columns[i] - 1] )
{
onC = offC;
offC = cmo.onClass;
}
$li = $("#" + cmo.listTargetID + " li").filter(function(){return this.cmData && this.cmData.col == columns[i] - 1;});
if ( onC )
{
$li.removeClass(onC);
}
if ( offC )
{
$li.addClass(offC);
}
}
}
saveCurrentValue(this);
});
};
/**
* Shows all table columns.
* When columns are passed through the parameter only the passed ones become visible.
*
* @param {integer|array} columns A number or an array of numbers. Each column with the matching column index will become visible.
* Column index starts at 1!
*
* @param {map} options An object for optional settings which will get passed to $().toggleColumns().
*
* @example $('#table').showColumns();
* @desc Sets the visibility state of all hidden columns to visible.
*
* @example $('#table').showColumns(3);
* @desc Show column number three.
*
* @type jQuery
*
* @name showColumns
* @cat Plugins/columnManager
* @author Roman Weich (http://p.sohei.org)
*/
$.fn.showColumns = function(columns, cmo)
{
return this.each(function()
{
var i,
cols = [],
cV = this.cMColsVisible;
if ( cV )
{
if ( columns && columns.constructor == Number )
columns = [columns];
for ( i = 0; i < cV.length; i++ )
{
//if there were no columns passed, show all - or else show only the columns the user wants to see
if ( !cV[i] && (!columns || $.inArray(i + 1, columns) > -1) )
cols.push(i + 1);
}
$(this).toggleColumns(cols, cmo);
}
});
};
/**
* Hides table columns.
*
* @param {integer|array} columns A number or an array of numbers. Each column with the matching column index will get hidden.
* Column index starts at 1!
*
* @param {map} options An object for optional settings which will get passed to $().toggleColumns().
*
* @example $('#table').hideColumns(3);
* @desc Hide column number three.
*
* @type jQuery
*
* @name hideColumns
* @cat Plugins/columnManager
* @author Roman Weich (http://p.sohei.org)
*/
$.fn.hideColumns = function(columns, cmo)
{
return this.each(function()
{
var i,
cols = columns,
cV = this.cMColsVisible;
if ( cV )
{
if ( columns.constructor == Number )
columns = [columns];
cols = [];
for ( i = 0; i < columns.length; i++ )
{
if ( cV[columns[i] - 1] || cV[columns[i] - 1] == undefined )
cols.push(columns[i]);
}
}
$(this).toggleColumns(cols, cmo);
});
};
})(jQuery);