      1 /*
      2  * File:        ColVis.js
      3  * Version:     1.0.4
      4  * CVS:         $Id$
      5  * Description: Controls for column visiblity in DataTables
      6  * Author:      Allan Jardine (www.sprymedia.co.uk)
      7  * Created:     Wed Sep 15 18:23:29 BST 2010
      8  * Modified:    $Date$ by $Author$
      9  * Language:    Javascript
     10  * License:     LGPL
     11  * Project:     Just a little bit of fun :-)
     12  * Contact:     www.sprymedia.co.uk/contact
     13  *
     14  * Copyright 2010 Allan Jardine, all rights reserved.
     15  *
     16  */
     17
     18 (function($) {
     19
     20 /**
     21  * ColVis provides column visiblity control for DataTables
     22  * @class ColVis
     23  * @constructor
     24  * @param {object} DataTables settings object
     25  */
     26 ColVis = function( oDTSettings, oInit )
     27 {
     28 	/* Santiy check that we are a new instance */
     29 	if ( !this.CLASS || this.CLASS != "ColVis" )
     30 	{
     31 		alert( "Warning: ColVis must be initialised with the keyword 'new'" );
     32 	}
     33
     34 	if ( typeof oInit == 'undefined' )
     35 	{
     36 		oInit = {};
     37 	}
     38
     39
     40 	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     41 	 * Public class variables
     42 	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
     43
     44 	/**
     45 	 * @namespace Settings object which contains customisable information for ColVis instance
     46 	 */
     47 	this.s = {
     48 		/**
     49 		 * DataTables settings object
     50 		 *  @property dt
     51 		 *  @type     Object
     52 		 *  @default  null
     53 		 */
     54 		dt: null,
     55
     56 		/**
     57 		 * Customisation object
     58 		 *  @property oInit
     59 		 *  @type     Object
     60 		 *  @default  passed in
     61 		 */
     62 		oInit: oInit,
     63
     64 		/**
     65 		 * Callback function to tell the user when the state has changed
     66 		 *  @property fnStateChange
     67 		 *  @type     function
     68 		 *  @default  null
     69 		 */
     70 		fnStateChange: null,
     71
     72 		/**
     73 		 * Mode of activation. Can be 'click' or 'mouseover'
     74 		 *  @property activate
     75 		 *  @type     String
     76 		 *  @default  click
     77 		 */
     78 		activate: "click",
     79
     80 		/**
     81 		 * Position of the collection menu when shown - align "left" or "right"
     82 		 *  @property sAlign
     83 		 *  @type     String
     84 		 *  @default  right
     85 		 */
     86 		sAlign: "left",
     87
     88 		/**
     89 		 * Text used for the button
     90 		 *  @property buttonText
     91 		 *  @type     String
     92 		 *  @default  Show / hide columns
     93 		 */
     94 		buttonText: "Show / hide columns",
     95
     96 		/**
     97 		 * Flag to say if the collection is hidden
     98 		 *  @property hidden
     99 		 *  @type     boolean
    100 		 *  @default  true
    101 		 */
    102 		hidden: true,
    103
    104 		/**
    105 		 * List of columns (integers) which should be excluded from the list
    106 		 *  @property aiExclude
    107 		 *  @type     Array
    108 		 *  @default  []
    109 		 */
    110 		aiExclude: [],
    111
    112 		/**
    113 		 * Store the original viisbility settings so they could be restored
    114 		 *  @property abOriginal
    115 		 *  @type     Array
    116 		 *  @default  []
    117 		 */
    118 		abOriginal: [],
    119
    120 		/**
    121 		 * Show restore button
    122 		 *  @property bRestore
    123 		 *  @type     Array
    124 		 *  @default  []
    125 		 */
    126 		bRestore: false,
    127
    128 		/**
    129 		 * Restore button text
    130 		 *  @property sRestore
    131 		 *  @type     String
    132 		 *  @default  Restore original
    133 		 */
    134 		sRestore: "Restore original"
    135 	};
    136
    137
    138 	/**
    139 	 * @namespace Common and useful DOM elements for the class instance
    140 	 */
    141 	this.dom = {
    142 		/**
    143 		 * Wrapper for the button - given back to DataTables as the node to insert
    144 		 *  @property wrapper
    145 		 *  @type     Node
    146 		 *  @default  null
    147 		 */
    148 		wrapper: null,
    149
    150 		/**
    151 		 * Activation button
    152 		 *  @property button
    153 		 *  @type     Node
    154 		 *  @default  null
    155 		 */
    156 		button: null,
    157
    158 		/**
    159 		 * Collection list node
    160 		 *  @property collection
    161 		 *  @type     Node
    162 		 *  @default  null
    163 		 */
    164 		collection: null,
    165
    166 		/**
    167 		 * Background node used for shading the display and event capturing
    168 		 *  @property background
    169 		 *  @type     Node
    170 		 *  @default  null
    171 		 */
    172 		background: null,
    173
    174 		/**
    175 		 * Element to position over the activation button to catch mouse events when using mouseover
    176 		 *  @property catcher
    177 		 *  @type     Node
    178 		 *  @default  null
    179 		 */
    180 		catcher: null,
    181
    182 		/**
    183 		 * List of button elements
    184 		 *  @property buttons
    185 		 *  @type     Array
    186 		 *  @default  []
    187 		 */
    188 		buttons: [],
    189
    190 		/**
    191 		 * Restore button
    192 		 *  @property restore
    193 		 *  @type     Node
    194 		 *  @default  null
    195 		 */
    196 		restore: null
    197 	};
    198
    199 	/* Store global reference */
    200 	ColVis.aInstances.push( this );
    201
    202 	/* Constructor logic */
    203 	this.s.dt = oDTSettings;
    204 	this._fnConstruct();
    205 	return this;
    206 };
    207
    208
    209
    210 ColVis.prototype = {
    211 	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    212 	 * Public methods
    213 	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    214
    215 	/**
    216 	 * Rebuild the list of buttons for this instance (i.e. if there is a column header update)
    217 	 *  @method  fnRebuild
    218 	 *  @returns void
    219 	 */
    220 	fnRebuild: function ()
    221 	{
    222 		/* Remove the old buttons */
    223 		for ( var i=this.dom.buttons.length-1 ; i>=0 ; i-- )
    224 		{
    225 			if ( this.dom.buttons[i] !== null )
    226 			{
    227 				this.dom.collection.removeChild( this.dom.buttons[i] );
    228 			}
    229 		}
    230 		this.dom.buttons.splice( 0, this.dom.buttons.length );
    231
    232 		if ( this.dom.restore )
    233 		{
    234 			this.dom.restore.parentNode( this.dom.restore );
    235 		}
    236
    237 		/* Re-add them (this is not the optimal way of doing this, it is fast and effective) */
    238 		this._fnAddButtons();
    239
    240 		/* Update the checkboxes */
    241 		this._fnDrawCallback();
    242 	},
    243
    244
    245
    246 	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    247 	 * Private methods (they are of course public in JS, but recommended as private)
    248 	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    249
    250 	/**
    251 	 * Constructor logic
    252 	 *  @method  _fnConstruct
    253 	 *  @returns void
    254 	 *  @private
    255 	 */
    256 	_fnConstruct: function ()
    257 	{
    258 		this._fnApplyCustomisation();
    259
    260 		var that = this;
    261 		this.dom.wrapper = document.createElement('div');
    262 		this.dom.wrapper.className = "ColVis TableTools";
    263
    264 		this.dom.button = this._fnDomBaseButton( this.s.buttonText );
    265 		this.dom.button.className += " ColVis_MasterButton";
    266 		this.dom.wrapper.appendChild( this.dom.button );
    267
    268 		this.dom.catcher = this._fnDomCatcher();
    269 		this.dom.collection = this._fnDomCollection();
    270 		this.dom.background = this._fnDomBackground();
    271
    272 		this._fnAddButtons();
    273
    274 		/* Store the original visbility information */
    275 		for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
    276 		{
    277 			this.s.abOriginal.push( this.s.dt.aoColumns[i].bVisible );
    278 		}
    279
    280 		/* Update on each draw */
    281 		this.s.dt.aoDrawCallback.push( {
    282 			fn: function () {
    283 				that._fnDrawCallback.call( that );
    284 			},
    285 			sName: "ColVis"
    286 		} );
    287 	},
    288
    289
    290 	/**
    291 	 * Apply any customisation to the settings from the DataTables initialisation
    292 	 *  @method  _fnApplyCustomisation
    293 	 *  @returns void
    294 	 *  @private
    295 	 */
    296 	_fnApplyCustomisation: function ()
    297 	{
    298 		var oConfig = this.s.oInit;
    299
    300 		if ( typeof oConfig.activate != 'undefined' )
    301 		{
    302 			this.s.activate = oConfig.activate;
    303 		}
    304
    305 		if ( typeof oConfig.buttonText != 'undefined' )
    306 		{
    307 			this.s.buttonText = oConfig.buttonText;
    308 		}
    309
    310 		if ( typeof oConfig.aiExclude != 'undefined' )
    311 		{
    312 			this.s.aiExclude = oConfig.aiExclude;
    313 		}
    314
    315 		if ( typeof oConfig.bRestore != 'undefined' )
    316 		{
    317 			this.s.bRestore = oConfig.bRestore;
    318 		}
    319
    320 		if ( typeof oConfig.sRestore != 'undefined' )
    321 		{
    322 			this.s.sRestore = oConfig.sRestore;
    323 		}
    324
    325 		if ( typeof oConfig.sAlign != 'undefined' )
    326 		{
    327 			this.s.sAlign = oConfig.sAlign;
    328 		}
    329
    330 		if ( typeof oConfig.fnStateChange != 'undefined' )
    331 		{
    332 			this.s.fnStateChange = oConfig.fnStateChange;
    333 		}
    334 	},
    335
    336
    337 	/**
    338 	 * On each table draw, check the visiblity checkboxes as needed. This allows any process to
    339 	 * update the table's column visiblity and ColVis will still be accurate.
    340 	 *  @method  _fnDrawCallback
    341 	 *  @returns void
    342 	 *  @private
    343 	 */
    344 	_fnDrawCallback: function ()
    345 	{
    346 		var aoColumns = this.s.dt.aoColumns;
    347
    348 		for ( var i=0, iLen=aoColumns.length ; i<iLen ; i++ )
    349 		{
    350 			if ( this.dom.buttons[i] !== null )
    351 			{
    352 				if ( aoColumns[i].bVisible )
    353 				{
    354 					$('input', this.dom.buttons[i]).attr('checked','checked');
    355 				}
    356 				else
    357 				{
    358 					$('input', this.dom.buttons[i]).removeAttr('checked');
    359 				}
    360 			}
    361 		}
    362 	},
    363
    364
    365 	/**
    366 	 * Loop through the columns in the table and as a new button for each one.
    367 	 *  @method  _fnAddButtons
    368 	 *  @returns void
    369 	 *  @private
    370 	 */
    371 	_fnAddButtons: function ()
    372 	{
    373 		var
    374 			nButton,
    375 			sExclude = ","+this.s.aiExclude.join(',')+",";
    376
    377 		for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
    378 		{
    379 			if ( sExclude.indexOf( ","+i+"," ) == -1 )
    380 			{
    381 				nButton = this._fnDomColumnButton( i );
    382 				this.dom.buttons.push( nButton );
    383 				this.dom.collection.appendChild( nButton );
    384 			}
    385 			else
    386 			{
    387 				this.dom.buttons.push( null );
    388 			}
    389 		}
    390
    391 		if ( this.s.bRestore )
    392 		{
    393 			nButton = this._fnDomRestoreButton();
    394 			nButton.className += " ColVis_Restore";
    395 			this.dom.buttons.push( nButton );
    396 			this.dom.collection.appendChild( nButton );
    397 		}
    398 	},
    399
    400
    401 	/**
    402 	 * Create a button which allows a "restore" action
    403 	 *  @method  _fnDomRestoreButton
    404 	 *  @returns {Node} Created button
    405 	 *  @private
    406 	 */
    407 	_fnDomRestoreButton: function ()
    408 	{
    409 		var
    410 			that = this,
    411 		  nButton = document.createElement('button'),
    412 		  nSpan = document.createElement('span');
    413
    414 		nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
    415 			"ColVis_Button TableTools_Button ui-button ui-state-default";
    416 		nButton.appendChild( nSpan );
    417 		$(nSpan).html( '<span class="ColVis_title">'+this.s.sRestore+'</span>' );
    418
    419 		$(nButton).click( function (e) {
    420 			for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
    421 			{
    422 				that.s.dt.oInstance.fnSetColumnVis( i, that.s.abOriginal[i], false );
    423 			}
    424 			that.s.dt.oInstance.fnDraw( false );
    425 		} );
    426
    427 		return nButton;
    428 	},
    429
    430
    431 	/**
    432 	 * Create the DOM for a show / hide button
    433 	 *  @method  _fnDomColumnButton
    434 	 *  @param {int} i Column in question
    435 	 *  @returns {Node} Created button
    436 	 *  @private
    437 	 */
    438 	_fnDomColumnButton: function ( i )
    439 	{
    440 		var
    441 			that = this,
    442 			oColumn = this.s.dt.aoColumns[i],
    443 		  nButton = document.createElement('button'),
    444 		  nSpan = document.createElement('span');
    445
    446 		nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
    447 			"ColVis_Button TableTools_Button ui-button ui-state-default";
    448 		nButton.appendChild( nSpan );
    449 		$(nSpan).html(
    450 			'<span class="ColVis_radio"><input type="checkbox"></span>'+
    451 			'<span class="ColVis_title">'+oColumn.sTitle+'</span>' );
    452
    453 		$(nButton).click( function (e) {
    454 			var showHide = $('input',this).attr('checked')===true ? false : true;
    455 			if ( e.target.nodeName.toLowerCase() == "input" )
    456 			{
    457 				showHide = $('input',this).attr('checked');
    458 			}
    459
    460 			/* Need to consider the case where the initialiser created more than one table - change the
    461 			 * API index that DataTables is using
    462 			 */
    463 			var oldIndex = $.fn.dataTableExt.iApiIndex;
    464 			$.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that);
    465 			that.s.dt.oInstance.fnSetColumnVis( i, showHide );
    466 			$.fn.dataTableExt.iApiIndex = oldIndex; /* Restore */
    467
    468 			if ( that.s.fnStateChange !== null )
    469 			{
    470 				that.s.fnStateChange.call( that, i, showHide );
    471 			}
    472 		} );
    473
    474 		return nButton;
    475 	},
    476
    477
    478 	/**
    479 	 * Get the position in the DataTables instance array of the table for this instance of ColVis
    480 	 *  @method  _fnDataTablesApiIndex
    481 	 *  @returns {int} Index
    482 	 *  @private
    483 	 */
    484 	_fnDataTablesApiIndex: function ()
    485 	{
    486 		for ( var i=0, iLen=this.s.dt.oInstance.length ; i<iLen ; i++ )
    487 		{
    488 			if ( this.s.dt.oInstance[i] == this.s.dt.nTable )
    489 			{
    490 				return i;
    491 			}
    492 		}
    493 		return 0;
    494 	},
    495
    496
    497 	/**
    498 	 * Create the DOM needed for the button and apply some base properties. All buttons start here
    499 	 *  @method  _fnDomBaseButton
    500 	 *  @param   {String} text Button text
    501 	 *  @returns {Node} DIV element for the button
    502 	 *  @private
    503 	 */
    504 	_fnDomBaseButton: function ( text )
    505 	{
    506 		var
    507 			that = this,
    508 		  nButton = document.createElement('button'),
    509 		  nSpan = document.createElement('span'),
    510 			sEvent = this.s.activate=="mouseover" ? "mouseover" : "click";
    511
    512 		nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
    513 			"ColVis_Button TableTools_Button ui-button ui-state-default";
    514 		nButton.appendChild( nSpan );
    515 		nSpan.innerHTML = text;
    516
    517 		$(nButton).bind( sEvent, function (e) {
    518 			that._fnCollectionShow();
    519 			e.preventDefault();
    520 		} );
    521
    522 		return nButton;
    523 	},
    524
    525
    526 	/**
    527 	 * Create the element used to contain list the columns (it is shown and hidden as needed)
    528 	 *  @method  _fnDomCollection
    529 	 *  @returns {Node} div container for the collection
    530 	 *  @private
    531 	 */
    532 	_fnDomCollection: function ()
    533 	{
    534 		var that = this;
    535 		var nHidden = document.createElement('div');
    536 		nHidden.style.display = "none";
    537 		nHidden.className = !this.s.dt.bJUI ? "ColVis_collection TableTools_collection" :
    538 			"ColVis_collection TableTools_collection ui-buttonset ui-buttonset-multi";
    539 		nHidden.style.position = "absolute";
    540 		$(nHidden).css('opacity', 0);
    541
    542 		return nHidden;
    543 	},
    544
    545
    546 	/**
    547 	 * An element to be placed on top of the activate button to catch events
    548 	 *  @method  _fnDomCatcher
    549 	 *  @returns {Node} div container for the collection
    550 	 *  @private
    551 	 */
    552 	_fnDomCatcher: function ()
    553 	{
    554 		var
    555 			that = this,
    556 			nCatcher = document.createElement('div');
    557 		nCatcher.className = "ColVis_catcher TableTools_catcher";
    558
    559 		$(nCatcher).click( function () {
    560 			that._fnCollectionHide.call( that, null, null );
    561 		} );
    562
    563 		return nCatcher;
    564 	},
    565
    566
    567 	/**
    568 	 * Create the element used to shade the background, and capture hide events (it is shown and
    569 	 * hidden as needed)
    570 	 *  @method  _fnDomBackground
    571 	 *  @returns {Node} div container for the background
    572 	 *  @private
    573 	 */
    574 	_fnDomBackground: function ()
    575 	{
    576 		var that = this;
    577
    578 		var nBackground = document.createElement('div');
    579 		nBackground.style.position = "absolute";
    580 		nBackground.style.left = "0px";
    581 		nBackground.style.top = "0px";
    582 		nBackground.className = "ColVis_collectionBackground TableTools_collectionBackground";
    583 		$(nBackground).css('opacity', 0);
    584
    585 		$(nBackground).click( function () {
    586 			that._fnCollectionHide.call( that, null, null );
    587 		} );
    588
    589 		/* When considering a mouse over action for the activation, we also consider a mouse out
    590 		 * which is the same as a mouse over the background - without all the messing around of
    591 		 * bubbling events. Use the catcher element to avoid messing around with bubbling
    592 		 */
    593 		if ( this.s.activate == "mouseover" )
    594 		{
    595 			$(nBackground).mouseover( function () {
    596 				that.s.overcollection = false;
    597 				that._fnCollectionHide.call( that, null, null );
    598 			} );
    599 		}
    600
    601 		return nBackground;
    602 	},
    603
    604
    605 	/**
    606 	 * Show the show / hide list and the background
    607 	 *  @method  _fnCollectionShow
    608 	 *  @returns void
    609 	 *  @private
    610 	 */
    611 	_fnCollectionShow: function ()
    612 	{
    613 		var that = this;
    614 		var oPos = $(this.dom.button).offset();
    615 		var nHidden = this.dom.collection;
    616 		var nBackground = this.dom.background;
    617 		var iDivX = parseInt(oPos.left, 10);
    618 		var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10);
    619
    620 		nHidden.style.top = iDivY+"px";
    621 		nHidden.style.left = iDivX+"px";
    622 		nHidden.style.display = "block";
    623 		$(nHidden).css('opacity',0);
    624
    625 		var iWinHeight = $(window).height(), iDocHeight = $(document).height(),
    626 		 	iWinWidth = $(window).width(), iDocWidth = $(document).width();
    627
    628 		nBackground.style.height = ((iWinHeight>iDocHeight)? iWinHeight : iDocHeight) +"px";
    629 		nBackground.style.width = ((iWinWidth<iDocWidth)? iWinWidth : iDocWidth) +"px";
    630
    631 		var oStyle = this.dom.catcher.style;
    632 		oStyle.height = $(this.dom.button).outerHeight()+"px";
    633 		oStyle.width = $(this.dom.button).outerWidth()+"px";
    634 		oStyle.top = oPos.top+"px";
    635 		oStyle.left = iDivX+"px";
    636
    637 		document.body.appendChild( nBackground );
    638 		document.body.appendChild( nHidden );
    639 		document.body.appendChild( this.dom.catcher );
    640
    641 		/* Visual corrections to try and keep the collection visible */
    642 		nHidden.style.left = this.s.sAlign=="left" ?
    643 			iDivX+"px" : (iDivX-$(nHidden).outerWidth()+$(this.dom.button).outerWidth())+"px";
    644
    645 		var iDivWidth = $(nHidden).outerWidth();
    646 		var iDivHeight = $(nHidden).outerHeight();
    647
    648 		if ( iDivX + iDivWidth > iDocWidth )
    649 		{
    650 			nHidden.style.left = (iDocWidth-iDivWidth)+"px";
    651 		}
    652
    653 		if ( iDivY + iDivHeight > iDocHeight )
    654 		{
    655 			nHidden.style.top = (iDivY-iDivHeight-$(this.dom.button).outerHeight())+"px";
    656 		}
    657
    658
    659 		/* This results in a very small delay for the end user but it allows the animation to be
    660 		 * much smoother. If you don't want the animation, then the setTimeout can be removed
    661 		 */
    662 		setTimeout( function () {
    663 			$(nHidden).animate({opacity: 1}, 500);
    664 			$(nBackground).animate({opacity: 0.1}, 500, 'linear', function () {
    665 				/* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually
    666 				 * reflected. As such, we need to do it here, once it is visible. Unbelievable.
    667 				 */
    668 				if ( jQuery.browser.msie && jQuery.browser.version == "6.0" )
    669 				{
    670 					that._fnDrawCallback();
    671 				}
    672 			});
    673 		}, 10 );
    674
    675 		this.s.hidden = false;
    676 	},
    677
    678
    679 	/**
    680 	 * Hide the show / hide list and the background
    681 	 *  @method  _fnCollectionHide
    682 	 *  @returns void
    683 	 *  @private
    684 	 */
    685 	_fnCollectionHide: function (  )
    686 	{
    687 		var that = this;
    688
    689 		if ( !this.s.hidden && this.dom.collection !== null )
    690 		{
    691 			this.s.hidden = true;
    692
    693 			$(this.dom.collection).animate({opacity: 0}, 500, function (e) {
    694 				this.style.display = "none";
    695 			} );
    696
    697 			$(this.dom.background).animate({opacity: 0}, 500, function (e) {
    698 				document.body.removeChild( that.dom.background );
    699 				document.body.removeChild( that.dom.catcher );
    700 			} );
    701 		}
    702 	}
    703 };
    704
    705
    706
    707
    708
    709 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    710  * Static object methods
    711  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    712
    713 /**
    714  * Rebuild the collection for a given table, or all tables if no parameter given
    715  *  @method  ColVis.fnRebuild
    716  *  @static
    717  *  @param   object oTable DataTable instance to consider - optional
    718  *  @returns void
    719  */
    720 ColVis.fnRebuild = function ( oTable )
    721 {
    722 	var nTable = null;
    723 	if ( typeof oTable != 'undefined' )
    724 	{
    725 		nTable = oTable.fnSettings().nTable;
    726 	}
    727
    728 	for ( var i=0, iLen=ColVis.aInstances.length ; i<iLen ; i++ )
    729 	{
    730 		if ( typeof oTable == 'undefined' || nTable == ColVis.aInstances[i].s.dt.nTable )
    731 		{
    732 			ColVis.aInstances[i].fnRebuild();
    733 		}
    734 	}
    735 };
    736
    737
    738
    739
    740
    741 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    742  * Static object propterties
    743  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    744
    745 /**
    746  * Collection of all ColVis instances
    747  *  @property ColVis.aInstances
    748  *  @static
    749  *  @type     Array
    750  *  @default  []
    751  */
    752 ColVis.aInstances = [];
    753
    754
    755
    756
    757
    758 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    759  * Constants
    760  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    761
    762 /**
    763  * Name of this class
    764  *  @constant CLASS
    765  *  @type     String
    766  *  @default  ColVis
    767  */
    768 ColVis.prototype.CLASS = "ColVis";
    769
    770
    771 /**
    772  * ColVis version
    773  *  @constant  VERSION
    774  *  @type      String
    775  *  @default   1.0.4.dev
    776  */
    777 ColVis.VERSION = "1.0.4";
    778 ColVis.prototype.VERSION = ColVis.VERSION;
    779
    780
    781
    782
    783
    784 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    785  * Initialisation
    786  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    787
    788 /*
    789  * Register a new feature with DataTables
    790  */
    791 if ( typeof $.fn.dataTable == "function" &&
    792      typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
    793      $.fn.dataTableExt.fnVersionCheck('1.7.0') )
    794 {
    795 	$.fn.dataTableExt.aoFeatures.push( {
    796 		fnInit: function( oDTSettings ) {
    797 			var init = (typeof oDTSettings.oInit.oColVis == 'undefined') ?
    798 				{} : oDTSettings.oInit.oColVis;
    799 			var oColvis = new ColVis( oDTSettings, init );
    800 			return oColvis.dom.wrapper;
    801 		},
    802 		cFeature: "C",
    803 		sFeature: "ColVis"
    804 	} );
    805 }
    806 else
    807 {
    808 	alert( "Warning: ColVis requires DataTables 1.7 or greater - www.datatables.net/download");
    809 }
    810
    811 })(jQuery);
    812