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