Blame | Letzte Änderung | Log anzeigen | RSS feed
/*! FixedHeader 2.1.2* ©2010-2014 SpryMedia Ltd - datatables.net/license*//*** @summary FixedHeader* @description Fix a table's header or footer, so it is always visible while* Scrolling* @version 2.1.2* @file dataTables.fixedHeader.js* @author SpryMedia Ltd (www.sprymedia.co.uk)* @contact www.sprymedia.co.uk/contact* @copyright Copyright 2009-2014 SpryMedia Ltd.** This source file is free software, available under the following license:* MIT license - http://datatables.net/license/mit** This source file is distributed in the hope that it will be useful, but* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.** For details please refer to: http://www.datatables.net*//* Global scope for FixedColumns for backwards compatibility - will be removed* in future. Not documented in 1.1.x.*//* Global scope for FixedColumns */var FixedHeader;(function(window, document, undefined) {var factory = function( $, DataTable ) {"use strict";/** Function: FixedHeader* Purpose: Provide 'fixed' header, footer and columns for a DataTable* Returns: object:FixedHeader - must be called with 'new'* Inputs: mixed:mTable - target table* @param {object} dt DataTables instance or HTML table node. With DataTables* 1.10 this can also be a jQuery collection (with just a single table in its* result set), a jQuery selector, DataTables API instance or settings* object.* @param {object} [oInit] initialisation settings, with the following* properties (each optional)* * bool:top - fix the header (default true)* * bool:bottom - fix the footer (default false)* * int:left - fix the left column(s) (default 0)* * int:right - fix the right column(s) (default 0)* * int:zTop - fixed header zIndex* * int:zBottom - fixed footer zIndex* * int:zLeft - fixed left zIndex* * int:zRight - fixed right zIndex*/FixedHeader = function ( mTable, oInit ) {/* Sanity check - you just know it will happen */if ( ! this instanceof FixedHeader ){alert( "FixedHeader warning: FixedHeader must be initialised with the 'new' keyword." );return;}var that = this;var oSettings = {"aoCache": [],"oSides": {"top": true,"bottom": false,"left": 0,"right": 0},"oZIndexes": {"top": 104,"bottom": 103,"left": 102,"right": 101},"oCloneOnDraw": {"top": false,"bottom": false,"left": true,"right": true},"oMes": {"iTableWidth": 0,"iTableHeight": 0,"iTableLeft": 0,"iTableRight": 0, /* note this is left+width, not actually "right" */"iTableTop": 0,"iTableBottom": 0 /* note this is top+height, not actually "bottom" */},"oOffset": {"top": 0},"nTable": null,"bFooter": false,"bInitComplete": false};/** Function: fnGetSettings* Purpose: Get the settings for this object* Returns: object: - settings object* Inputs: -*/this.fnGetSettings = function () {return oSettings;};/** Function: fnUpdate* Purpose: Update the positioning and copies of the fixed elements* Returns: -* Inputs: -*/this.fnUpdate = function () {this._fnUpdateClones();this._fnUpdatePositions();};/** Function: fnPosition* Purpose: Update the positioning of the fixed elements* Returns: -* Inputs: -*/this.fnPosition = function () {this._fnUpdatePositions();};var dt = $.fn.dataTable.Api ?new $.fn.dataTable.Api( mTable ).settings()[0] :mTable.fnSettings();dt._oPluginFixedHeader = this;/* Let's do it */this.fnInit( dt, oInit );};/** Variable: FixedHeader* Purpose: Prototype for FixedHeader* Scope: global*/FixedHeader.prototype = {/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Initialisation*//** Function: fnInit* Purpose: The "constructor"* Returns: -* Inputs: {as FixedHeader function}*/fnInit: function ( oDtSettings, oInit ){var s = this.fnGetSettings();var that = this;/* Record the user definable settings */this.fnInitSettings( s, oInit );if ( oDtSettings.oScroll.sX !== "" || oDtSettings.oScroll.sY !== "" ){alert( "FixedHeader 2 is not supported with DataTables' scrolling mode at this time" );return;}s.nTable = oDtSettings.nTable;oDtSettings.aoDrawCallback.unshift( {"fn": function () {FixedHeader.fnMeasure();that._fnUpdateClones.call(that);that._fnUpdatePositions.call(that);},"sName": "FixedHeader"} );s.bFooter = ($('>tfoot', s.nTable).length > 0) ? true : false;/* Add the 'sides' that are fixed */if ( s.oSides.top ){s.aoCache.push( that._fnCloneTable( "fixedHeader", "FixedHeader_Header", that._fnCloneThead ) );}if ( s.oSides.bottom ){s.aoCache.push( that._fnCloneTable( "fixedFooter", "FixedHeader_Footer", that._fnCloneTfoot ) );}if ( s.oSides.left ){s.aoCache.push( that._fnCloneTable( "fixedLeft", "FixedHeader_Left", that._fnCloneTLeft, s.oSides.left ) );}if ( s.oSides.right ){s.aoCache.push( that._fnCloneTable( "fixedRight", "FixedHeader_Right", that._fnCloneTRight, s.oSides.right ) );}/* Event listeners for window movement */FixedHeader.afnScroll.push( function () {that._fnUpdatePositions.call(that);} );$(window).resize( function () {FixedHeader.fnMeasure();that._fnUpdateClones.call(that);that._fnUpdatePositions.call(that);} );$(s.nTable).on('column-reorder.dt', function () {FixedHeader.fnMeasure();that._fnUpdateClones( true );that._fnUpdatePositions();} ).on('column-visibility.dt', function () {FixedHeader.fnMeasure();that._fnUpdateClones( true );that._fnUpdatePositions();} );/* Get things right to start with */FixedHeader.fnMeasure();that._fnUpdateClones();that._fnUpdatePositions();s.bInitComplete = true;},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Support functions*//** Function: fnInitSettings* Purpose: Take the user's settings and copy them to our local store* Returns: -* Inputs: object:s - the local settings object* object:oInit - the user's settings object*/fnInitSettings: function ( s, oInit ){if ( oInit !== undefined ){if ( oInit.top !== undefined ) {s.oSides.top = oInit.top;}if ( oInit.bottom !== undefined ) {s.oSides.bottom = oInit.bottom;}if ( typeof oInit.left == 'boolean' ) {s.oSides.left = oInit.left ? 1 : 0;}else if ( oInit.left !== undefined ) {s.oSides.left = oInit.left;}if ( typeof oInit.right == 'boolean' ) {s.oSides.right = oInit.right ? 1 : 0;}else if ( oInit.right !== undefined ) {s.oSides.right = oInit.right;}if ( oInit.zTop !== undefined ) {s.oZIndexes.top = oInit.zTop;}if ( oInit.zBottom !== undefined ) {s.oZIndexes.bottom = oInit.zBottom;}if ( oInit.zLeft !== undefined ) {s.oZIndexes.left = oInit.zLeft;}if ( oInit.zRight !== undefined ) {s.oZIndexes.right = oInit.zRight;}if ( oInit.offsetTop !== undefined ) {s.oOffset.top = oInit.offsetTop;}if ( oInit.alwaysCloneTop !== undefined ) {s.oCloneOnDraw.top = oInit.alwaysCloneTop;}if ( oInit.alwaysCloneBottom !== undefined ) {s.oCloneOnDraw.bottom = oInit.alwaysCloneBottom;}if ( oInit.alwaysCloneLeft !== undefined ) {s.oCloneOnDraw.left = oInit.alwaysCloneLeft;}if ( oInit.alwaysCloneRight !== undefined ) {s.oCloneOnDraw.right = oInit.alwaysCloneRight;}}},/** Function: _fnCloneTable* Purpose: Clone the table node and do basic initialisation* Returns: -* Inputs: -*/_fnCloneTable: function ( sType, sClass, fnClone, iCells ){var s = this.fnGetSettings();var nCTable;/* We know that the table _MUST_ has a DIV wrapped around it, because this is simply how* DataTables works. Therefore, we can set this to be relatively position (if it is not* alreadu absolute, and use this as the base point for the cloned header*/if ( $(s.nTable.parentNode).css('position') != "absolute" ){s.nTable.parentNode.style.position = "relative";}/* Just a shallow clone will do - we only want the table node */nCTable = s.nTable.cloneNode( false );nCTable.removeAttribute( 'id' );var nDiv = document.createElement( 'div' );nDiv.style.position = "absolute";nDiv.style.top = "0px";nDiv.style.left = "0px";nDiv.className += " FixedHeader_Cloned "+sType+" "+sClass;/* Set the zIndexes */if ( sType == "fixedHeader" ){nDiv.style.zIndex = s.oZIndexes.top;}if ( sType == "fixedFooter" ){nDiv.style.zIndex = s.oZIndexes.bottom;}if ( sType == "fixedLeft" ){nDiv.style.zIndex = s.oZIndexes.left;}else if ( sType == "fixedRight" ){nDiv.style.zIndex = s.oZIndexes.right;}/* remove margins since we are going to position it absolutely */nCTable.style.margin = "0";/* Insert the newly cloned table into the DOM, on top of the "real" header */nDiv.appendChild( nCTable );document.body.appendChild( nDiv );return {"nNode": nCTable,"nWrapper": nDiv,"sType": sType,"sPosition": "","sTop": "","sLeft": "","fnClone": fnClone,"iCells": iCells};},/** Function: _fnMeasure* Purpose: Get the current positioning of the table in the DOM* Returns: -* Inputs: -*/_fnMeasure: function (){vars = this.fnGetSettings(),m = s.oMes,jqTable = $(s.nTable),oOffset = jqTable.offset(),iParentScrollTop = this._fnSumScroll( s.nTable.parentNode, 'scrollTop' ),iParentScrollLeft = this._fnSumScroll( s.nTable.parentNode, 'scrollLeft' );m.iTableWidth = jqTable.outerWidth();m.iTableHeight = jqTable.outerHeight();m.iTableLeft = oOffset.left + s.nTable.parentNode.scrollLeft;m.iTableTop = oOffset.top + iParentScrollTop;m.iTableRight = m.iTableLeft + m.iTableWidth;m.iTableRight = FixedHeader.oDoc.iWidth - m.iTableLeft - m.iTableWidth;m.iTableBottom = FixedHeader.oDoc.iHeight - m.iTableTop - m.iTableHeight;},/** Function: _fnSumScroll* Purpose: Sum node parameters all the way to the top* Returns: int: sum* Inputs: node:n - node to consider* string:side - scrollTop or scrollLeft*/_fnSumScroll: function ( n, side ){var i = n[side];while ( n = n.parentNode ){if ( n.nodeName == 'HTML' || n.nodeName == 'BODY' ){break;}i = n[side];}return i;},/** Function: _fnUpdatePositions* Purpose: Loop over the fixed elements for this table and update their positions* Returns: -* Inputs: -*/_fnUpdatePositions: function (){var s = this.fnGetSettings();this._fnMeasure();for ( var i=0, iLen=s.aoCache.length ; i<iLen ; i++ ){if ( s.aoCache[i].sType == "fixedHeader" ){this._fnScrollFixedHeader( s.aoCache[i] );}else if ( s.aoCache[i].sType == "fixedFooter" ){this._fnScrollFixedFooter( s.aoCache[i] );}else if ( s.aoCache[i].sType == "fixedLeft" ){this._fnScrollHorizontalLeft( s.aoCache[i] );}else{this._fnScrollHorizontalRight( s.aoCache[i] );}}},/** Function: _fnUpdateClones* Purpose: Loop over the fixed elements for this table and call their cloning functions* Returns: -* Inputs: -*/_fnUpdateClones: function ( full ){var s = this.fnGetSettings();if ( full ) {// This is a little bit of a hack to force a full clone draw. When// `full` is set to true, we want to reclone the source elements,// regardless of the clone-on-draw settingss.bInitComplete = false;}for ( var i=0, iLen=s.aoCache.length ; i<iLen ; i++ ){s.aoCache[i].fnClone.call( this, s.aoCache[i] );}if ( full ) {s.bInitComplete = true;}},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Scrolling functions*//** Function: _fnScrollHorizontalLeft* Purpose: Update the positioning of the scrolling elements* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnScrollHorizontalRight: function ( oCache ){vars = this.fnGetSettings(),oMes = s.oMes,oWin = FixedHeader.oWin,oDoc = FixedHeader.oDoc,nTable = oCache.nWrapper,iFixedWidth = $(nTable).outerWidth();if ( oWin.iScrollRight < oMes.iTableRight ){/* Fully right aligned */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft+oMes.iTableWidth-iFixedWidth)+"px", 'left', nTable.style );}else if ( oMes.iTableLeft < oDoc.iWidth-oWin.iScrollRight-iFixedWidth ){/* Middle */this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', (oWin.iWidth-iFixedWidth)+"px", 'left', nTable.style );}else{/* Fully left aligned */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}},/** Function: _fnScrollHorizontalLeft* Purpose: Update the positioning of the scrolling elements* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnScrollHorizontalLeft: function ( oCache ){vars = this.fnGetSettings(),oMes = s.oMes,oWin = FixedHeader.oWin,oDoc = FixedHeader.oDoc,nTable = oCache.nWrapper,iCellWidth = $(nTable).outerWidth();if ( oWin.iScrollLeft < oMes.iTableLeft ){/* Fully left align */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}else if ( oWin.iScrollLeft < oMes.iTableLeft+oMes.iTableWidth-iCellWidth ){this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', "0px", 'left', nTable.style );}else{/* Fully right align */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft+oMes.iTableWidth-iCellWidth)+"px", 'left', nTable.style );}},/** Function: _fnScrollFixedFooter* Purpose: Update the positioning of the scrolling elements* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnScrollFixedFooter: function ( oCache ){vars = this.fnGetSettings(),oMes = s.oMes,oWin = FixedHeader.oWin,oDoc = FixedHeader.oDoc,nTable = oCache.nWrapper,iTheadHeight = $("thead", s.nTable).outerHeight(),iCellHeight = $(nTable).outerHeight();if ( oWin.iScrollBottom < oMes.iTableBottom ){/* Below */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+oMes.iTableHeight-iCellHeight)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}else if ( oWin.iScrollBottom < oMes.iTableBottom+oMes.iTableHeight-iCellHeight-iTheadHeight ){this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oWin.iHeight-iCellHeight)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style );}else{/* Above */this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iCellHeight)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}},/** Function: _fnScrollFixedHeader* Purpose: Update the positioning of the scrolling elements* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnScrollFixedHeader: function ( oCache ){vars = this.fnGetSettings(),oMes = s.oMes,oWin = FixedHeader.oWin,oDoc = FixedHeader.oDoc,nTable = oCache.nWrapper,iTbodyHeight = 0,anTbodies = s.nTable.getElementsByTagName('tbody');for (var i = 0; i < anTbodies.length; ++i) {iTbodyHeight += anTbodies[i].offsetHeight;}if ( oMes.iTableTop > oWin.iScrollTop + s.oOffset.top ){/* Above the table */this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}else if ( oWin.iScrollTop + s.oOffset.top > oMes.iTableTop+iTbodyHeight ){/* At the bottom of the table */this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iTbodyHeight)+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );}else{/* In the middle of the table */this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );this._fnUpdateCache( oCache, 'sTop', s.oOffset.top+"px", 'top', nTable.style );this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style );}},/** Function: _fnUpdateCache* Purpose: Check the cache and update cache and value if needed* Returns: -* Inputs: object:oCache - local cache object* string:sCache - cache property* string:sSet - value to set* string:sProperty - object property to set* object:oObj - object to update*/_fnUpdateCache: function ( oCache, sCache, sSet, sProperty, oObj ){if ( oCache[sCache] != sSet ){oObj[sProperty] = sSet;oCache[sCache] = sSet;}},/*** Copy the classes of all child nodes from one element to another. This implies* that the two have identical structure - no error checking is performed to that* fact.* @param {element} source Node to copy classes from* @param {element} dest Node to copy classes too*/_fnClassUpdate: function ( source, dest ){var that = this;if ( source.nodeName.toUpperCase() === "TR" || source.nodeName.toUpperCase() === "TH" ||source.nodeName.toUpperCase() === "TD" || source.nodeName.toUpperCase() === "SPAN" ){dest.className = source.className;}$(source).children().each( function (i) {that._fnClassUpdate( $(source).children()[i], $(dest).children()[i] );} );},/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Cloning functions*//** Function: _fnCloneThead* Purpose: Clone the thead element* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnCloneThead: function ( oCache ){var s = this.fnGetSettings();var nTable = oCache.nNode;if ( s.bInitComplete && !s.oCloneOnDraw.top ){this._fnClassUpdate( $('thead', s.nTable)[0], $('thead', nTable)[0] );return;}/* Set the wrapper width to match that of the cloned table */var iDtWidth = $(s.nTable).outerWidth();oCache.nWrapper.style.width = iDtWidth+"px";nTable.style.width = iDtWidth+"px";/* Remove any children the cloned table has */while ( nTable.childNodes.length > 0 ){$('thead th', nTable).unbind( 'click' );nTable.removeChild( nTable.childNodes[0] );}/* Clone the DataTables header */var nThead = $('thead', s.nTable).clone(true)[0];nTable.appendChild( nThead );/* Copy the widths across - apparently a clone isn't good enough for this */var a = [];var b = [];$("thead>tr th", s.nTable).each( function (i) {a.push( $(this).width() );} );$("thead>tr td", s.nTable).each( function (i) {b.push( $(this).width() );} );$("thead>tr th", s.nTable).each( function (i) {$("thead>tr th:eq("+i+")", nTable).width( a[i] );$(this).width( a[i] );} );$("thead>tr td", s.nTable).each( function (i) {$("thead>tr td:eq("+i+")", nTable).width( b[i] );$(this).width( b[i] );} );// Stop DataTables 1.9 from putting a focus ring on the headers when// clicked to sort$('th.sorting, th.sorting_desc, th.sorting_asc', nTable).bind( 'click', function () {this.blur();} );},/** Function: _fnCloneTfoot* Purpose: Clone the tfoot element* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnCloneTfoot: function ( oCache ){var s = this.fnGetSettings();var nTable = oCache.nNode;/* Set the wrapper width to match that of the cloned table */oCache.nWrapper.style.width = $(s.nTable).outerWidth()+"px";/* Remove any children the cloned table has */while ( nTable.childNodes.length > 0 ){nTable.removeChild( nTable.childNodes[0] );}/* Clone the DataTables footer */var nTfoot = $('tfoot', s.nTable).clone(true)[0];nTable.appendChild( nTfoot );/* Copy the widths across - apparently a clone isn't good enough for this */$("tfoot:eq(0)>tr th", s.nTable).each( function (i) {$("tfoot:eq(0)>tr th:eq("+i+")", nTable).width( $(this).width() );} );$("tfoot:eq(0)>tr td", s.nTable).each( function (i) {$("tfoot:eq(0)>tr td:eq("+i+")", nTable).width( $(this).width() );} );},/** Function: _fnCloneTLeft* Purpose: Clone the left column(s)* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnCloneTLeft: function ( oCache ){var s = this.fnGetSettings();var nTable = oCache.nNode;var nBody = $('tbody', s.nTable)[0];/* Remove any children the cloned table has */while ( nTable.childNodes.length > 0 ){nTable.removeChild( nTable.childNodes[0] );}/* Is this the most efficient way to do this - it looks horrible... */nTable.appendChild( $("thead", s.nTable).clone(true)[0] );nTable.appendChild( $("tbody", s.nTable).clone(true)[0] );if ( s.bFooter ){nTable.appendChild( $("tfoot", s.nTable).clone(true)[0] );}/* Remove unneeded cells */var sSelector = 'gt(' + (oCache.iCells - 1) + ')';$('thead tr', nTable).each( function (k) {$('th:' + sSelector, this).remove();} );$('tfoot tr', nTable).each( function (k) {$('th:' + sSelector, this).remove();} );$('tbody tr', nTable).each( function (k) {$('td:' + sSelector, this).remove();} );this.fnEqualiseHeights( 'thead', nBody.parentNode, nTable );this.fnEqualiseHeights( 'tbody', nBody.parentNode, nTable );this.fnEqualiseHeights( 'tfoot', nBody.parentNode, nTable );var iWidth = 0;for (var i = 0; i < oCache.iCells; i++) {iWidth += $('thead tr th:eq(' + i + ')', s.nTable).outerWidth();}nTable.style.width = iWidth+"px";oCache.nWrapper.style.width = iWidth+"px";},/** Function: _fnCloneTRight* Purpose: Clone the right most column(s)* Returns: -* Inputs: object:oCache - the cached values for this fixed element*/_fnCloneTRight: function ( oCache ){var s = this.fnGetSettings();var nBody = $('tbody', s.nTable)[0];var nTable = oCache.nNode;var iCols = $('tbody tr:eq(0) td', s.nTable).length;/* Remove any children the cloned table has */while ( nTable.childNodes.length > 0 ){nTable.removeChild( nTable.childNodes[0] );}/* Is this the most efficient way to do this - it looks horrible... */nTable.appendChild( $("thead", s.nTable).clone(true)[0] );nTable.appendChild( $("tbody", s.nTable).clone(true)[0] );if ( s.bFooter ){nTable.appendChild( $("tfoot", s.nTable).clone(true)[0] );}$('thead tr th:lt('+(iCols-oCache.iCells)+')', nTable).remove();$('tfoot tr th:lt('+(iCols-oCache.iCells)+')', nTable).remove();/* Remove unneeded cells */$('tbody tr', nTable).each( function (k) {$('td:lt('+(iCols-oCache.iCells)+')', this).remove();} );this.fnEqualiseHeights( 'thead', nBody.parentNode, nTable );this.fnEqualiseHeights( 'tbody', nBody.parentNode, nTable );this.fnEqualiseHeights( 'tfoot', nBody.parentNode, nTable );var iWidth = 0;for (var i = 0; i < oCache.iCells; i++) {iWidth += $('thead tr th:eq('+(iCols-1-i)+')', s.nTable).outerWidth();}nTable.style.width = iWidth+"px";oCache.nWrapper.style.width = iWidth+"px";},/*** Equalise the heights of the rows in a given table node in a cross browser way. Note that this* is more or less lifted as is from FixedColumns* @method fnEqualiseHeights* @returns void* @param {string} parent Node type - thead, tbody or tfoot* @param {element} original Original node to take the heights from* @param {element} clone Copy the heights to* @private*/"fnEqualiseHeights": function ( parent, original, clone ){var that = this;var originals = $(parent +' tr', original);var height;$(parent+' tr', clone).each( function (k) {height = originals.eq( k ).css('height');// This is nasty :-(. IE has a sub-pixel error even when setting// the height below (the Firefox fix) which causes the fixed column// to go out of alignment. Need to add a pixel before the assignment// Can this be feature detected? Not sure how...if ( navigator.appName == 'Microsoft Internet Explorer' ) {height = parseInt( height, 10 ) + 1;}$(this).css( 'height', height );// For Firefox to work, we need to also set the height of the// original row, to the value that we read from it! Otherwise there// is a sub-pixel rounding errororiginals.eq( k ).css( 'height', height );} );}};/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Static properties and methods* We use these for speed! This information is common to all instances of FixedHeader, so no* point if having them calculated and stored for each different instance.*//** Variable: oWin* Purpose: Store information about the window positioning* Scope: FixedHeader*/FixedHeader.oWin = {"iScrollTop": 0,"iScrollRight": 0,"iScrollBottom": 0,"iScrollLeft": 0,"iHeight": 0,"iWidth": 0};/** Variable: oDoc* Purpose: Store information about the document size* Scope: FixedHeader*/FixedHeader.oDoc = {"iHeight": 0,"iWidth": 0};/** Variable: afnScroll* Purpose: Array of functions that are to be used for the scrolling components* Scope: FixedHeader*/FixedHeader.afnScroll = [];/** Function: fnMeasure* Purpose: Update the measurements for the window and document* Returns: -* Inputs: -*/FixedHeader.fnMeasure = function (){varjqWin = $(window),jqDoc = $(document),oWin = FixedHeader.oWin,oDoc = FixedHeader.oDoc;oDoc.iHeight = jqDoc.height();oDoc.iWidth = jqDoc.width();oWin.iHeight = jqWin.height();oWin.iWidth = jqWin.width();oWin.iScrollTop = jqWin.scrollTop();oWin.iScrollLeft = jqWin.scrollLeft();oWin.iScrollRight = oDoc.iWidth - oWin.iScrollLeft - oWin.iWidth;oWin.iScrollBottom = oDoc.iHeight - oWin.iScrollTop - oWin.iHeight;};FixedHeader.version = "2.1.2";/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Global processing*//** Just one 'scroll' event handler in FixedHeader, which calls the required components. This is* done as an optimisation, to reduce calculation and proagation time*/$(window).scroll( function () {FixedHeader.fnMeasure();for ( var i=0, iLen=FixedHeader.afnScroll.length ; i<iLen ; i++ ) {FixedHeader.afnScroll[i]();}} );$.fn.dataTable.FixedHeader = FixedHeader;$.fn.DataTable.FixedHeader = FixedHeader;return FixedHeader;}; // /factory// Define as an AMD module if possibleif ( typeof define === 'function' && define.amd ) {define( ['jquery', 'datatables'], factory );}else if ( typeof exports === 'object' ) {// Node/CommonJSfactory( require('jquery'), require('datatables') );}else if ( jQuery && !jQuery.fn.dataTable.FixedHeader ) {// Otherwise simply initialise as normal, stopping multiple evaluationfactory( jQuery, jQuery.fn.dataTable );}})(window, document);