'
+ )
+ .click( function (e) {
+ var showHide = !$('input', this).is(":checked");
+ if ( e.target.nodeName.toLowerCase() !== "li" )
+ {
+ showHide = ! showHide;
+ }
+
+ /* Need to consider the case where the initialiser created more than one table - change the
+ * API index that DataTables is using
+ */
+ var oldIndex = $.fn.dataTableExt.iApiIndex;
+ $.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that);
+
+ // Optimisation for server-side processing when scrolling - don't do a full redraw
+ if ( dt.oFeatures.bServerSide )
+ {
+ that.s.dt.oInstance.fnSetColumnVis( i, showHide, false );
+ that.s.dt.oInstance.fnAdjustColumnSizing( false );
+ if (dt.oScroll.sX !== "" || dt.oScroll.sY !== "" )
+ {
+ that.s.dt.oInstance.oApi._fnScrollDraw( that.s.dt );
+ }
+ that._fnDrawCallback();
+ }
+ else
+ {
+ that.s.dt.oInstance.fnSetColumnVis( i, showHide );
+ }
+
+ $.fn.dataTableExt.iApiIndex = oldIndex; /* Restore */
+
+ if ( e.target.nodeName.toLowerCase() === 'input' && that.s.fnStateChange !== null )
+ {
+ that.s.fnStateChange.call( that, i, showHide );
+ }
+ } )[0];
+ },
+
+
+ /**
+ * Get the position in the DataTables instance array of the table for this
+ * instance of ColVis
+ * @method _fnDataTablesApiIndex
+ * @returns {int} Index
+ * @private
+ */
+ "_fnDataTablesApiIndex": function ()
+ {
+ for ( var i=0, iLen=this.s.dt.oInstance.length ; i', {
+ 'class': !this.s.dt.bJUI ?
+ "ColVis_collection" :
+ "ColVis_collection ui-buttonset ui-buttonset-multi"
+ } )
+ .css( {
+ 'display': 'none',
+ 'opacity': 0,
+ 'position': ! this.s.bCssPosition ?
+ 'absolute' :
+ ''
+ } )[0];
+ },
+
+
+ /**
+ * An element to be placed on top of the activate button to catch events
+ * @method _fnDomCatcher
+ * @returns {Node} div container for the collection
+ * @private
+ */
+ "_fnDomCatcher": function ()
+ {
+ var
+ that = this,
+ nCatcher = document.createElement('div');
+ nCatcher.className = "ColVis_catcher";
+
+ $(nCatcher).click( function () {
+ that._fnCollectionHide.call( that, null, null );
+ } );
+
+ return nCatcher;
+ },
+
+
+ /**
+ * Create the element used to shade the background, and capture hide events (it is shown and
+ * hidden as needed)
+ * @method _fnDomBackground
+ * @returns {Node} div container for the background
+ * @private
+ */
+ "_fnDomBackground": function ()
+ {
+ var that = this;
+
+ var background = $('')
+ .addClass( 'ColVis_collectionBackground' )
+ .css( 'opacity', 0 )
+ .click( function () {
+ that._fnCollectionHide.call( that, null, null );
+ } );
+
+ /* When considering a mouse over action for the activation, we also consider a mouse out
+ * which is the same as a mouse over the background - without all the messing around of
+ * bubbling events. Use the catcher element to avoid messing around with bubbling
+ */
+ if ( this.s.activate == "mouseover" )
+ {
+ background.mouseover( function () {
+ that.s.overcollection = false;
+ that._fnCollectionHide.call( that, null, null );
+ } );
+ }
+
+ return background[0];
+ },
+
+
+ /**
+ * Show the show / hide list and the background
+ * @method _fnCollectionShow
+ * @returns void
+ * @private
+ */
+ "_fnCollectionShow": function ()
+ {
+ var that = this, i, iLen, iLeft;
+ var oPos = $(this.dom.button).offset();
+ var nHidden = this.dom.collection;
+ var nBackground = this.dom.background;
+ var iDivX = parseInt(oPos.left, 10);
+ var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10);
+
+ if ( ! this.s.bCssPosition )
+ {
+ nHidden.style.top = iDivY+"px";
+ nHidden.style.left = iDivX+"px";
+ }
+
+ $(nHidden).css( {
+ 'display': 'block',
+ 'opacity': 0
+ } );
+
+ nBackground.style.bottom ='0px';
+ nBackground.style.right = '0px';
+
+ var oStyle = this.dom.catcher.style;
+ oStyle.height = $(this.dom.button).outerHeight()+"px";
+ oStyle.width = $(this.dom.button).outerWidth()+"px";
+ oStyle.top = oPos.top+"px";
+ oStyle.left = iDivX+"px";
+
+ document.body.appendChild( nBackground );
+ document.body.appendChild( nHidden );
+ document.body.appendChild( this.dom.catcher );
+
+ /* This results in a very small delay for the end user but it allows the animation to be
+ * much smoother. If you don't want the animation, then the setTimeout can be removed
+ */
+ $(nHidden).animate({"opacity": 1}, that.s.iOverlayFade);
+ $(nBackground).animate({"opacity": 0.1}, that.s.iOverlayFade, 'linear', function () {
+ /* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually
+ * reflected. As such, we need to do it here, once it is visible. Unbelievable.
+ */
+ if ( $.browser && $.browser.msie && $.browser.version == "6.0" )
+ {
+ that._fnDrawCallback();
+ }
+ });
+
+ /* Visual corrections to try and keep the collection visible */
+ if ( !this.s.bCssPosition )
+ {
+ iLeft = ( this.s.sAlign=="left" ) ?
+ iDivX :
+ iDivX - $(nHidden).outerWidth() + $(this.dom.button).outerWidth();
+
+ nHidden.style.left = iLeft+"px";
+
+ var iDivWidth = $(nHidden).outerWidth();
+ var iDivHeight = $(nHidden).outerHeight();
+ var iDocWidth = $(document).width();
+
+ if ( iLeft + iDivWidth > iDocWidth )
+ {
+ nHidden.style.left = (iDocWidth-iDivWidth)+"px";
+ }
+ }
+
+ this.s.hidden = false;
+ },
+
+
+ /**
+ * Hide the show / hide list and the background
+ * @method _fnCollectionHide
+ * @returns void
+ * @private
+ */
+ "_fnCollectionHide": function ( )
+ {
+ var that = this;
+
+ if ( !this.s.hidden && this.dom.collection !== null )
+ {
+ this.s.hidden = true;
+
+ $(this.dom.collection).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
+ this.style.display = "none";
+ } );
+
+ $(this.dom.background).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
+ document.body.removeChild( that.dom.background );
+ document.body.removeChild( that.dom.catcher );
+ } );
+ }
+ },
+
+
+ /**
+ * Alter the colspan on any fnOpen rows
+ */
+ "_fnAdjustOpenRows": function ()
+ {
+ var aoOpen = this.s.dt.aoOpenRows;
+ var iVisible = this.s.dt.oApi._fnVisbleColumns( this.s.dt );
+
+ for ( var i=0, iLen=aoOpen.length ; i