2016-04-22 00:37:33 +00:00
/ * ! F i x e d C o l u m n s 3 . 0 . 4
2015-12-13 09:34:12 +00:00
* © 2010 - 2014 SpryMedia Ltd - datatables . net / license
* /
/ * *
* @ summary FixedColumns
* @ description Freeze columns in place on a scrolling DataTable
2016-04-22 00:37:33 +00:00
* @ version 3.0 . 4
2015-12-13 09:34:12 +00:00
* @ file dataTables . fixedColumns . js
* @ author SpryMedia Ltd ( www . sprymedia . co . uk )
* @ contact www . sprymedia . co . uk / contact
* @ copyright Copyright 2010 - 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
* /
( function ( window , document , undefined ) {
var factory = function ( $ , DataTable ) {
"use strict" ;
/ * *
* When making use of DataTables ' x - axis scrolling feature , you may wish to
* fix the left most column in place . This plug - in for DataTables provides
* exactly this option ( note for non - scrolling tables , please use the
* FixedHeader plug - in , which can fix headers , footers and columns ) . Key
* features include :
*
* * Freezes the left or right most columns to the side of the table
* * Option to freeze two or more columns
* * Full integration with DataTables ' scrolling options
* * Speed - FixedColumns is fast in its operation
*
* @ class
* @ constructor
* @ global
* @ param { object } dt DataTables instance . With DataTables 1.10 this can also
* be a jQuery collection , a jQuery selector , DataTables API instance or
* settings object .
* @ param { object } [ init = { } ] Configuration object for FixedColumns . Options are
* defined by { @ link FixedColumns . defaults }
*
* @ requires jQuery 1.7 +
* @ requires DataTables 1.8 . 0 +
*
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* new $ . fn . dataTable . fixedColumns ( table ) ;
* /
var FixedColumns = function ( dt , init ) {
var that = this ;
/* Sanity check - you just know it will happen */
2016-04-22 00:37:33 +00:00
if ( ! ( this instanceof FixedColumns ) )
2015-12-13 09:34:12 +00:00
{
alert ( "FixedColumns warning: FixedColumns must be initialised with the 'new' keyword." ) ;
return ;
}
if ( typeof init == 'undefined' )
{
init = { } ;
}
// Use the DataTables Hungarian notation mapping method, if it exists to
// provide forwards compatibility for camel case variables
2016-04-22 00:37:33 +00:00
var camelToHungarian = $ . fn . dataTable . camelToHungarian ;
if ( camelToHungarian ) {
camelToHungarian ( FixedColumns . defaults , FixedColumns . defaults , true ) ;
camelToHungarian ( FixedColumns . defaults , init ) ;
2015-12-13 09:34:12 +00:00
}
// v1.10 allows the settings object to be got form a number of sources
var dtSettings = $ . fn . dataTable . Api ?
new $ . fn . dataTable . Api ( dt ) . settings ( ) [ 0 ] :
dt . fnSettings ( ) ;
/ * *
* Settings object which contains customisable information for FixedColumns instance
* @ namespace
* @ extends FixedColumns . defaults
* @ private
* /
this . s = {
/ * *
* DataTables settings objects
* @ type object
* @ default Obtained from DataTables instance
* /
"dt" : dtSettings ,
/ * *
* Number of columns in the DataTable - stored for quick access
* @ type int
* @ default Obtained from DataTables instance
* /
"iTableColumns" : dtSettings . aoColumns . length ,
/ * *
* Original outer widths of the columns as rendered by DataTables - used to calculate
* the FixedColumns grid bounding box
* @ type array . < int >
* @ default [ ]
* /
"aiOuterWidths" : [ ] ,
/ * *
* Original inner widths of the columns as rendered by DataTables - used to apply widths
* to the columns
* @ type array . < int >
* @ default [ ]
* /
"aiInnerWidths" : [ ]
} ;
/ * *
* DOM elements used by the class instance
* @ namespace
* @ private
*
* /
this . dom = {
/ * *
* DataTables scrolling element
* @ type node
* @ default null
* /
"scroller" : null ,
/ * *
* DataTables header table
* @ type node
* @ default null
* /
"header" : null ,
/ * *
* DataTables body table
* @ type node
* @ default null
* /
"body" : null ,
/ * *
* DataTables footer table
* @ type node
* @ default null
* /
"footer" : null ,
/ * *
* Display grid elements
* @ namespace
* /
"grid" : {
/ * *
* Grid wrapper . This is the container element for the 3 x3 grid
* @ type node
* @ default null
* /
"wrapper" : null ,
/ * *
* DataTables scrolling element . This element is the DataTables
* component in the display grid ( making up the main table - i . e .
* not the fixed columns ) .
* @ type node
* @ default null
* /
"dt" : null ,
/ * *
* Left fixed column grid components
* @ namespace
* /
"left" : {
"wrapper" : null ,
"head" : null ,
"body" : null ,
"foot" : null
} ,
/ * *
* Right fixed column grid components
* @ namespace
* /
"right" : {
"wrapper" : null ,
"head" : null ,
"body" : null ,
"foot" : null
}
} ,
/ * *
* Cloned table nodes
* @ namespace
* /
"clone" : {
/ * *
* Left column cloned table nodes
* @ namespace
* /
"left" : {
/ * *
* Cloned header table
* @ type node
* @ default null
* /
"header" : null ,
/ * *
* Cloned body table
* @ type node
* @ default null
* /
"body" : null ,
/ * *
* Cloned footer table
* @ type node
* @ default null
* /
"footer" : null
} ,
/ * *
* Right column cloned table nodes
* @ namespace
* /
"right" : {
/ * *
* Cloned header table
* @ type node
* @ default null
* /
"header" : null ,
/ * *
* Cloned body table
* @ type node
* @ default null
* /
"body" : null ,
/ * *
* Cloned footer table
* @ type node
* @ default null
* /
"footer" : null
}
}
} ;
/* Attach the instance to the DataTables instance so it can be accessed easily */
dtSettings . _oFixedColumns = this ;
/* Let's do it */
if ( ! dtSettings . _bInitComplete )
{
dtSettings . oApi . _fnCallbackReg ( dtSettings , 'aoInitComplete' , function ( ) {
that . _fnConstruct ( init ) ;
} , 'FixedColumns' ) ;
}
else
{
this . _fnConstruct ( init ) ;
}
} ;
FixedColumns . prototype = /** @lends FixedColumns.prototype */ {
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Public methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* Update the fixed columns - including headers and footers . Note that FixedColumns will
* automatically update the display whenever the host DataTable redraws .
* @ returns { void }
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* var fc = new $ . fn . dataTable . fixedColumns ( table ) ;
*
* // at some later point when the table has been manipulated....
* fc . fnUpdate ( ) ;
* /
"fnUpdate" : function ( )
{
this . _fnDraw ( true ) ;
} ,
/ * *
* Recalculate the resizes of the 3 x3 grid that FixedColumns uses for display of the table .
* This is useful if you update the width of the table container . Note that FixedColumns will
* perform this function automatically when the window . resize event is fired .
* @ returns { void }
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* var fc = new $ . fn . dataTable . fixedColumns ( table ) ;
*
* // Resize the table container and then have FixedColumns adjust its layout....
* $ ( '#content' ) . width ( 1200 ) ;
* fc . fnRedrawLayout ( ) ;
* /
"fnRedrawLayout" : function ( )
{
this . _fnColCalc ( ) ;
this . _fnGridLayout ( ) ;
this . fnUpdate ( ) ;
} ,
/ * *
* Mark a row such that it 's height should be recalculated when using ' semiauto ' row
* height matching . This function will have no effect when 'none' or 'auto' row height
* matching is used .
* @ param { Node } nTr TR element that should have it ' s height recalculated
* @ returns { void }
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* var fc = new $ . fn . dataTable . fixedColumns ( table ) ;
*
* // manipulate the table - mark the row as needing an update then update the table
* // this allows the redraw performed by DataTables fnUpdate to recalculate the row
* // height
* fc . fnRecalculateHeight ( ) ;
* table . fnUpdate ( $ ( '#example tbody tr:eq(0)' ) [ 0 ] , [ "insert date" , 1 , 2 , 3 ... ] ) ;
* /
"fnRecalculateHeight" : function ( nTr )
{
delete nTr . _DTTC _iHeight ;
nTr . style . height = 'auto' ;
} ,
/ * *
* Set the height of a given row - provides cross browser compatibility
* @ param { Node } nTarget TR element that should have it ' s height recalculated
* @ param { int } iHeight Height in pixels to set
* @ returns { void }
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* var fc = new $ . fn . dataTable . fixedColumns ( table ) ;
*
* // You may want to do this after manipulating a row in the fixed column
* fc . fnSetRowHeight ( $ ( '#example tbody tr:eq(0)' ) [ 0 ] , 50 ) ;
* /
"fnSetRowHeight" : function ( nTarget , iHeight )
{
nTarget . style . height = iHeight + "px" ;
} ,
/ * *
* Get data index information about a row or cell in the table body .
* This function is functionally identical to fnGetPosition in DataTables ,
* taking the same parameter ( TH , TD or TR node ) and returning exactly the
* the same information ( data index information ) . THe difference between
* the two is that this method takes into account the fixed columns in the
* table , so you can pass in nodes from the master table , or the cloned
* tables and get the index position for the data in the main table .
* @ param { node } node TR , TH or TD element to get the information about
* @ returns { int } If nNode is given as a TR , then a single index is
* returned , or if given as a cell , an array of [ row index , column index
* ( visible ) , column index ( all ) ] is given .
* /
"fnGetPosition" : function ( node )
{
var idx ;
var inst = this . s . dt . oInstance ;
if ( ! $ ( node ) . parents ( '.DTFC_Cloned' ) . length )
{
// Not in a cloned table
return inst . fnGetPosition ( node ) ;
}
else
{
// Its in the cloned table, so need to look up position
if ( node . nodeName . toLowerCase ( ) === 'tr' ) {
idx = $ ( node ) . index ( ) ;
return inst . fnGetPosition ( $ ( 'tr' , this . s . dt . nTBody ) [ idx ] ) ;
}
else
{
var colIdx = $ ( node ) . index ( ) ;
idx = $ ( node . parentNode ) . index ( ) ;
var row = inst . fnGetPosition ( $ ( 'tr' , this . s . dt . nTBody ) [ idx ] ) ;
return [
row ,
colIdx ,
inst . oApi . _fnVisibleToColumnIndex ( this . s . dt , colIdx )
] ;
}
}
} ,
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Private methods ( they are of course public in JS , but recommended as private )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* Initialisation for FixedColumns
* @ param { Object } oInit User settings for initialisation
* @ returns { void }
* @ private
* /
"_fnConstruct" : function ( oInit )
{
var i , iLen , iWidth ,
that = this ;
/* Sanity checking */
if ( typeof this . s . dt . oInstance . fnVersionCheck != 'function' ||
this . s . dt . oInstance . fnVersionCheck ( '1.8.0' ) !== true )
{
alert ( "FixedColumns " + FixedColumns . VERSION + " required DataTables 1.8.0 or later. " +
"Please upgrade your DataTables installation" ) ;
return ;
}
if ( this . s . dt . oScroll . sX === "" )
{
this . s . dt . oInstance . oApi . _fnLog ( this . s . dt , 1 , "FixedColumns is not needed (no " +
"x-scrolling in DataTables enabled), so no action will be taken. Use 'FixedHeader' for " +
"column fixing when scrolling is not enabled" ) ;
return ;
}
/* Apply the settings from the user / defaults */
this . s = $ . extend ( true , this . s , FixedColumns . defaults , oInit ) ;
/* Set up the DOM as we need it and cache nodes */
var classes = this . s . dt . oClasses ;
this . dom . grid . dt = $ ( this . s . dt . nTable ) . parents ( 'div.' + classes . sScrollWrapper ) [ 0 ] ;
this . dom . scroller = $ ( 'div.' + classes . sScrollBody , this . dom . grid . dt ) [ 0 ] ;
/* Set up the DOM that we want for the fixed column layout grid */
this . _fnColCalc ( ) ;
this . _fnGridSetup ( ) ;
/* Event handlers */
var mouseController ;
// When the body is scrolled - scroll the left and right columns
$ ( this . dom . scroller )
. on ( 'mouseover.DTFC touchstart.DTFC' , function ( ) {
mouseController = 'main' ;
} )
. on ( 'scroll.DTFC' , function ( ) {
if ( mouseController === 'main' ) {
if ( that . s . iLeftColumns > 0 ) {
that . dom . grid . left . liner . scrollTop = that . dom . scroller . scrollTop ;
}
if ( that . s . iRightColumns > 0 ) {
that . dom . grid . right . liner . scrollTop = that . dom . scroller . scrollTop ;
}
}
} ) ;
var wheelType = 'onwheel' in document . createElement ( 'div' ) ?
'wheel.DTFC' :
'mousewheel.DTFC' ;
if ( that . s . iLeftColumns > 0 ) {
// When scrolling the left column, scroll the body and right column
$ ( that . dom . grid . left . liner )
. on ( 'mouseover.DTFC touchstart.DTFC' , function ( ) {
mouseController = 'left' ;
} )
. on ( 'scroll.DTFC' , function ( ) {
if ( mouseController === 'left' ) {
that . dom . scroller . scrollTop = that . dom . grid . left . liner . scrollTop ;
if ( that . s . iRightColumns > 0 ) {
that . dom . grid . right . liner . scrollTop = that . dom . grid . left . liner . scrollTop ;
}
}
} )
. on ( wheelType , function ( e ) { // xxx update the destroy as well
// Pass horizontal scrolling through
var xDelta = e . type === 'wheel' ?
- e . originalEvent . deltaX :
e . originalEvent . wheelDeltaX ;
that . dom . scroller . scrollLeft -= xDelta ;
} ) ;
}
if ( that . s . iRightColumns > 0 ) {
// When scrolling the right column, scroll the body and the left column
$ ( that . dom . grid . right . liner )
. on ( 'mouseover.DTFC touchstart.DTFC' , function ( ) {
mouseController = 'right' ;
} )
. on ( 'scroll.DTFC' , function ( ) {
if ( mouseController === 'right' ) {
that . dom . scroller . scrollTop = that . dom . grid . right . liner . scrollTop ;
if ( that . s . iLeftColumns > 0 ) {
that . dom . grid . left . liner . scrollTop = that . dom . grid . right . liner . scrollTop ;
}
}
} )
. on ( wheelType , function ( e ) {
// Pass horizontal scrolling through
var xDelta = e . type === 'wheel' ?
- e . originalEvent . deltaX :
e . originalEvent . wheelDeltaX ;
that . dom . scroller . scrollLeft -= xDelta ;
} ) ;
}
$ ( window ) . on ( 'resize.DTFC' , function ( ) {
that . _fnGridLayout . call ( that ) ;
} ) ;
var bFirstDraw = true ;
var jqTable = $ ( this . s . dt . nTable ) ;
jqTable
. on ( 'draw.dt.DTFC' , function ( ) {
that . _fnDraw . call ( that , bFirstDraw ) ;
bFirstDraw = false ;
} )
. on ( 'column-sizing.dt.DTFC' , function ( ) {
that . _fnColCalc ( ) ;
that . _fnGridLayout ( that ) ;
} )
. on ( 'column-visibility.dt.DTFC' , function ( ) {
that . _fnColCalc ( ) ;
that . _fnGridLayout ( that ) ;
that . _fnDraw ( true ) ;
} )
. on ( 'destroy.dt.DTFC' , function ( ) {
jqTable . off ( 'column-sizing.dt.DTFC destroy.dt.DTFC draw.dt.DTFC' ) ;
$ ( that . dom . scroller ) . off ( 'scroll.DTFC mouseover.DTFC' ) ;
$ ( window ) . off ( 'resize.DTFC' ) ;
$ ( that . dom . grid . left . liner ) . off ( 'scroll.DTFC mouseover.DTFC ' + wheelType ) ;
$ ( that . dom . grid . left . wrapper ) . remove ( ) ;
$ ( that . dom . grid . right . liner ) . off ( 'scroll.DTFC mouseover.DTFC ' + wheelType ) ;
$ ( that . dom . grid . right . wrapper ) . remove ( ) ;
} ) ;
/ * G e t t h i n g s r i g h t t o s t a r t w i t h - n o t e t h a t d u e t o a d j u s t i n g t h e c o l u m n s , t h e r e m u s t b e
* another redraw of the main table . It doesn ' t need to be a full redraw however .
* /
this . _fnGridLayout ( ) ;
this . s . dt . oInstance . fnDraw ( false ) ;
} ,
/ * *
* Calculate the column widths for the grid layout
* @ returns { void }
* @ private
* /
"_fnColCalc" : function ( )
{
var that = this ;
var iLeftWidth = 0 ;
var iRightWidth = 0 ;
this . s . aiInnerWidths = [ ] ;
this . s . aiOuterWidths = [ ] ;
$ . each ( this . s . dt . aoColumns , function ( i , col ) {
var th = $ ( col . nTh ) ;
var border ;
if ( ! th . filter ( ':visible' ) . length ) {
that . s . aiInnerWidths . push ( 0 ) ;
that . s . aiOuterWidths . push ( 0 ) ;
}
else
{
// Inner width is used to assign widths to cells
// Outer width is used to calculate the container
var iWidth = th . outerWidth ( ) ;
// When working with the left most-cell, need to add on the
// table's border to the outerWidth, since we need to take
// account of it, but it isn't in any cell
if ( that . s . aiOuterWidths . length === 0 ) {
border = $ ( that . s . dt . nTable ) . css ( 'border-left-width' ) ;
iWidth += typeof border === 'string' ? 1 : parseInt ( border , 10 ) ;
}
// Likewise with the final column on the right
if ( that . s . aiOuterWidths . length === that . s . dt . aoColumns . length - 1 ) {
border = $ ( that . s . dt . nTable ) . css ( 'border-right-width' ) ;
iWidth += typeof border === 'string' ? 1 : parseInt ( border , 10 ) ;
}
that . s . aiOuterWidths . push ( iWidth ) ;
that . s . aiInnerWidths . push ( th . width ( ) ) ;
if ( i < that . s . iLeftColumns )
{
iLeftWidth += iWidth ;
}
if ( that . s . iTableColumns - that . s . iRightColumns <= i )
{
iRightWidth += iWidth ;
}
}
} ) ;
this . s . iLeftWidth = iLeftWidth ;
this . s . iRightWidth = iRightWidth ;
} ,
/ * *
* Set up the DOM for the fixed column . The way the layout works is to create a 1 x3 grid
* for the left column , the DataTable ( for which we just reuse the scrolling element DataTable
* puts into the DOM ) and the right column . In each of he two fixed column elements there is a
* grouping wrapper element and then a head , body and footer wrapper . In each of these we then
* place the cloned header , body or footer tables . This effectively gives as 3 x3 grid structure .
* @ returns { void }
* @ private
* /
"_fnGridSetup" : function ( )
{
var that = this ;
var oOverflow = this . _fnDTOverflow ( ) ;
var block ;
this . dom . body = this . s . dt . nTable ;
this . dom . header = this . s . dt . nTHead . parentNode ;
this . dom . header . parentNode . parentNode . style . position = "relative" ;
var nSWrapper =
$ ( '<div class="DTFC_ScrollWrapper" style="position:relative; clear:both;">' +
'<div class="DTFC_LeftWrapper" style="position:absolute; top:0; left:0;">' +
'<div class="DTFC_LeftHeadWrapper" style="position:relative; top:0; left:0; overflow:hidden;"></div>' +
'<div class="DTFC_LeftBodyWrapper" style="position:relative; top:0; left:0; overflow:hidden;">' +
'<div class="DTFC_LeftBodyLiner" style="position:relative; top:0; left:0; overflow-y:scroll;"></div>' +
'</div>' +
'<div class="DTFC_LeftFootWrapper" style="position:relative; top:0; left:0; overflow:hidden;"></div>' +
'</div>' +
'<div class="DTFC_RightWrapper" style="position:absolute; top:0; left:0;">' +
'<div class="DTFC_RightHeadWrapper" style="position:relative; top:0; left:0;">' +
'<div class="DTFC_RightHeadBlocker DTFC_Blocker" style="position:absolute; top:0; bottom:0;"></div>' +
'</div>' +
'<div class="DTFC_RightBodyWrapper" style="position:relative; top:0; left:0; overflow:hidden;">' +
'<div class="DTFC_RightBodyLiner" style="position:relative; top:0; left:0; overflow-y:scroll;"></div>' +
'</div>' +
'<div class="DTFC_RightFootWrapper" style="position:relative; top:0; left:0;">' +
'<div class="DTFC_RightFootBlocker DTFC_Blocker" style="position:absolute; top:0; bottom:0;"></div>' +
'</div>' +
'</div>' +
'</div>' ) [ 0 ] ;
var nLeft = nSWrapper . childNodes [ 0 ] ;
var nRight = nSWrapper . childNodes [ 1 ] ;
this . dom . grid . dt . parentNode . insertBefore ( nSWrapper , this . dom . grid . dt ) ;
nSWrapper . appendChild ( this . dom . grid . dt ) ;
this . dom . grid . wrapper = nSWrapper ;
if ( this . s . iLeftColumns > 0 )
{
this . dom . grid . left . wrapper = nLeft ;
this . dom . grid . left . head = nLeft . childNodes [ 0 ] ;
this . dom . grid . left . body = nLeft . childNodes [ 1 ] ;
this . dom . grid . left . liner = $ ( 'div.DTFC_LeftBodyLiner' , nSWrapper ) [ 0 ] ;
nSWrapper . appendChild ( nLeft ) ;
}
if ( this . s . iRightColumns > 0 )
{
this . dom . grid . right . wrapper = nRight ;
this . dom . grid . right . head = nRight . childNodes [ 0 ] ;
this . dom . grid . right . body = nRight . childNodes [ 1 ] ;
this . dom . grid . right . liner = $ ( 'div.DTFC_RightBodyLiner' , nSWrapper ) [ 0 ] ;
block = $ ( 'div.DTFC_RightHeadBlocker' , nSWrapper ) [ 0 ] ;
block . style . width = oOverflow . bar + "px" ;
block . style . right = - oOverflow . bar + "px" ;
this . dom . grid . right . headBlock = block ;
block = $ ( 'div.DTFC_RightFootBlocker' , nSWrapper ) [ 0 ] ;
block . style . width = oOverflow . bar + "px" ;
block . style . right = - oOverflow . bar + "px" ;
this . dom . grid . right . footBlock = block ;
nSWrapper . appendChild ( nRight ) ;
}
if ( this . s . dt . nTFoot )
{
this . dom . footer = this . s . dt . nTFoot . parentNode ;
if ( this . s . iLeftColumns > 0 )
{
this . dom . grid . left . foot = nLeft . childNodes [ 2 ] ;
}
if ( this . s . iRightColumns > 0 )
{
this . dom . grid . right . foot = nRight . childNodes [ 2 ] ;
}
}
} ,
/ * *
* Style and position the grid used for the FixedColumns layout
* @ returns { void }
* @ private
* /
"_fnGridLayout" : function ( )
{
var oGrid = this . dom . grid ;
var iWidth = $ ( oGrid . wrapper ) . width ( ) ;
var iBodyHeight = $ ( this . s . dt . nTable . parentNode ) . outerHeight ( ) ;
var iFullHeight = $ ( this . s . dt . nTable . parentNode . parentNode ) . outerHeight ( ) ;
var oOverflow = this . _fnDTOverflow ( ) ;
var
iLeftWidth = this . s . iLeftWidth ,
iRightWidth = this . s . iRightWidth ,
iRight ;
2016-04-22 00:37:33 +00:00
var scrollbarAdjust = function ( node , width ) {
if ( ! oOverflow . bar ) {
// If there is no scrollbar (Macs) we need to hide the auto scrollbar
node . style . width = ( width + 20 ) + "px" ;
node . style . paddingRight = "20px" ;
node . style . boxSizing = "border-box" ;
}
else {
// Otherwise just overflow by the scrollbar
node . style . width = ( width + oOverflow . bar ) + "px" ;
}
} ;
2015-12-13 09:34:12 +00:00
// When x scrolling - don't paint the fixed columns over the x scrollbar
if ( oOverflow . x )
{
iBodyHeight -= oOverflow . bar ;
}
oGrid . wrapper . style . height = iFullHeight + "px" ;
if ( this . s . iLeftColumns > 0 )
{
oGrid . left . wrapper . style . width = iLeftWidth + "px" ;
oGrid . left . wrapper . style . height = "1px" ;
oGrid . left . body . style . height = iBodyHeight + "px" ;
if ( oGrid . left . foot ) {
oGrid . left . foot . style . top = ( oOverflow . x ? oOverflow . bar : 0 ) + "px" ; // shift footer for scrollbar
}
2016-04-22 00:37:33 +00:00
scrollbarAdjust ( oGrid . left . liner , iLeftWidth ) ;
2015-12-13 09:34:12 +00:00
oGrid . left . liner . style . height = iBodyHeight + "px" ;
}
if ( this . s . iRightColumns > 0 )
{
iRight = iWidth - iRightWidth ;
if ( oOverflow . y )
{
iRight -= oOverflow . bar ;
}
oGrid . right . wrapper . style . width = iRightWidth + "px" ;
oGrid . right . wrapper . style . left = iRight + "px" ;
oGrid . right . wrapper . style . height = "1px" ;
oGrid . right . body . style . height = iBodyHeight + "px" ;
if ( oGrid . right . foot ) {
oGrid . right . foot . style . top = ( oOverflow . x ? oOverflow . bar : 0 ) + "px" ;
}
2016-04-22 00:37:33 +00:00
scrollbarAdjust ( oGrid . right . liner , iRightWidth ) ;
2015-12-13 09:34:12 +00:00
oGrid . right . liner . style . height = iBodyHeight + "px" ;
oGrid . right . headBlock . style . display = oOverflow . y ? 'block' : 'none' ;
oGrid . right . footBlock . style . display = oOverflow . y ? 'block' : 'none' ;
}
} ,
/ * *
* Get information about the DataTable ' s scrolling state - specifically if the table is scrolling
* on either the x or y axis , and also the scrollbar width .
* @ returns { object } Information about the DataTables scrolling state with the properties :
* 'x' , 'y' and 'bar'
* @ private
* /
"_fnDTOverflow" : function ( )
{
var nTable = this . s . dt . nTable ;
var nTableScrollBody = nTable . parentNode ;
var out = {
"x" : false ,
"y" : false ,
"bar" : this . s . dt . oScroll . iBarWidth
} ;
if ( nTable . offsetWidth > nTableScrollBody . clientWidth )
{
out . x = true ;
}
if ( nTable . offsetHeight > nTableScrollBody . clientHeight )
{
out . y = true ;
}
return out ;
} ,
/ * *
* Clone and position the fixed columns
* @ returns { void }
* @ param { Boolean } bAll Indicate if the header and footer should be updated as well ( true )
* @ private
* /
"_fnDraw" : function ( bAll )
{
this . _fnGridLayout ( ) ;
this . _fnCloneLeft ( bAll ) ;
this . _fnCloneRight ( bAll ) ;
/* Draw callback function */
if ( this . s . fnDrawCallback !== null )
{
this . s . fnDrawCallback . call ( this , this . dom . clone . left , this . dom . clone . right ) ;
}
/* Event triggering */
$ ( this ) . trigger ( 'draw.dtfc' , {
"leftClone" : this . dom . clone . left ,
"rightClone" : this . dom . clone . right
} ) ;
} ,
/ * *
* Clone the right columns
* @ returns { void }
* @ param { Boolean } bAll Indicate if the header and footer should be updated as well ( true )
* @ private
* /
"_fnCloneRight" : function ( bAll )
{
if ( this . s . iRightColumns <= 0 ) {
return ;
}
var that = this ,
i , jq ,
aiColumns = [ ] ;
for ( i = this . s . iTableColumns - this . s . iRightColumns ; i < this . s . iTableColumns ; i ++ ) {
if ( this . s . dt . aoColumns [ i ] . bVisible ) {
aiColumns . push ( i ) ;
}
}
this . _fnClone ( this . dom . clone . right , this . dom . grid . right , aiColumns , bAll ) ;
} ,
/ * *
* Clone the left columns
* @ returns { void }
* @ param { Boolean } bAll Indicate if the header and footer should be updated as well ( true )
* @ private
* /
"_fnCloneLeft" : function ( bAll )
{
if ( this . s . iLeftColumns <= 0 ) {
return ;
}
var that = this ,
i , jq ,
aiColumns = [ ] ;
for ( i = 0 ; i < this . s . iLeftColumns ; i ++ ) {
if ( this . s . dt . aoColumns [ i ] . bVisible ) {
aiColumns . push ( i ) ;
}
}
this . _fnClone ( this . dom . clone . left , this . dom . grid . left , aiColumns , bAll ) ;
} ,
/ * *
* Make a copy of the layout object for a header or footer element from DataTables . Note that
* this method will clone the nodes in the layout object .
* @ returns { Array } Copy of the layout array
* @ param { Object } aoOriginal Layout array from DataTables ( aoHeader or aoFooter )
* @ param { Object } aiColumns Columns to copy
* @ private
* /
"_fnCopyLayout" : function ( aoOriginal , aiColumns )
{
var aReturn = [ ] ;
var aClones = [ ] ;
var aCloned = [ ] ;
for ( var i = 0 , iLen = aoOriginal . length ; i < iLen ; i ++ )
{
var aRow = [ ] ;
aRow . nTr = $ ( aoOriginal [ i ] . nTr ) . clone ( true , true ) [ 0 ] ;
for ( var j = 0 , jLen = this . s . iTableColumns ; j < jLen ; j ++ )
{
if ( $ . inArray ( j , aiColumns ) === - 1 )
{
continue ;
}
var iCloned = $ . inArray ( aoOriginal [ i ] [ j ] . cell , aCloned ) ;
if ( iCloned === - 1 )
{
var nClone = $ ( aoOriginal [ i ] [ j ] . cell ) . clone ( true , true ) [ 0 ] ;
aClones . push ( nClone ) ;
aCloned . push ( aoOriginal [ i ] [ j ] . cell ) ;
aRow . push ( {
"cell" : nClone ,
"unique" : aoOriginal [ i ] [ j ] . unique
} ) ;
}
else
{
aRow . push ( {
"cell" : aClones [ iCloned ] ,
"unique" : aoOriginal [ i ] [ j ] . unique
} ) ;
}
}
aReturn . push ( aRow ) ;
}
return aReturn ;
} ,
/ * *
* Clone the DataTable nodes and place them in the DOM ( sized correctly )
* @ returns { void }
* @ param { Object } oClone Object containing the header , footer and body cloned DOM elements
* @ param { Object } oGrid Grid object containing the display grid elements for the cloned
* column ( left or right )
* @ param { Array } aiColumns Column indexes which should be operated on from the DataTable
* @ param { Boolean } bAll Indicate if the header and footer should be updated as well ( true )
* @ private
* /
"_fnClone" : function ( oClone , oGrid , aiColumns , bAll )
{
var that = this ,
i , iLen , j , jLen , jq , nTarget , iColumn , nClone , iIndex , aoCloneLayout ,
2016-04-22 00:37:33 +00:00
jqCloneThead , aoFixedHeader ,
dt = this . s . dt ;
2015-12-13 09:34:12 +00:00
/ *
* Header
* /
if ( bAll )
{
if ( oClone . header !== null )
{
oClone . header . parentNode . removeChild ( oClone . header ) ;
}
oClone . header = $ ( this . dom . header ) . clone ( true , true ) [ 0 ] ;
oClone . header . className += " DTFC_Cloned" ;
oClone . header . style . width = "100%" ;
oGrid . head . appendChild ( oClone . header ) ;
/* Copy the DataTables layout cache for the header for our floating column */
2016-04-22 00:37:33 +00:00
aoCloneLayout = this . _fnCopyLayout ( dt . aoHeader , aiColumns ) ;
2015-12-13 09:34:12 +00:00
jqCloneThead = $ ( '>thead' , oClone . header ) ;
jqCloneThead . empty ( ) ;
/* Add the created cloned TR elements to the table */
for ( i = 0 , iLen = aoCloneLayout . length ; i < iLen ; i ++ )
{
jqCloneThead [ 0 ] . appendChild ( aoCloneLayout [ i ] . nTr ) ;
}
/ * U s e t h e h a n d y _ f n D r a w H e a d f u n c t i o n i n D a t a T a b l e s t o d o t h e r o w s p a n / c o l s p a n
* calculations for us
* /
2016-04-22 00:37:33 +00:00
dt . oApi . _fnDrawHead ( dt , aoCloneLayout , true ) ;
2015-12-13 09:34:12 +00:00
}
else
{
/ * T o e n s u r e t h a t w e c o p y c e l l c l a s s e s e x a c t l y , r e g a r d l e s s o f c o l s p a n , m u l t i p l e r o w s
* etc , we make a copy of the header from the DataTable again , but don ' t insert the
* cloned cells , just copy the classes across . To get the matching layout for the
* fixed component , we use the DataTables _fnDetectHeader method , allowing 1 : 1 mapping
* /
2016-04-22 00:37:33 +00:00
aoCloneLayout = this . _fnCopyLayout ( dt . aoHeader , aiColumns ) ;
2015-12-13 09:34:12 +00:00
aoFixedHeader = [ ] ;
2016-04-22 00:37:33 +00:00
dt . oApi . _fnDetectHeader ( aoFixedHeader , $ ( '>thead' , oClone . header ) [ 0 ] ) ;
2015-12-13 09:34:12 +00:00
for ( i = 0 , iLen = aoCloneLayout . length ; i < iLen ; i ++ )
{
for ( j = 0 , jLen = aoCloneLayout [ i ] . length ; j < jLen ; j ++ )
{
aoFixedHeader [ i ] [ j ] . cell . className = aoCloneLayout [ i ] [ j ] . cell . className ;
// If jQuery UI theming is used we need to copy those elements as well
$ ( 'span.DataTables_sort_icon' , aoFixedHeader [ i ] [ j ] . cell ) . each ( function ( ) {
this . className = $ ( 'span.DataTables_sort_icon' , aoCloneLayout [ i ] [ j ] . cell ) [ 0 ] . className ;
} ) ;
}
}
}
this . _fnEqualiseHeights ( 'thead' , this . dom . header , oClone . header ) ;
/ *
* Body
* /
if ( this . s . sHeightMatch == 'auto' )
{
/* Remove any heights which have been applied already and let the browser figure it out */
$ ( '>tbody>tr' , that . dom . body ) . css ( 'height' , 'auto' ) ;
}
if ( oClone . body !== null )
{
oClone . body . parentNode . removeChild ( oClone . body ) ;
oClone . body = null ;
}
oClone . body = $ ( this . dom . body ) . clone ( true ) [ 0 ] ;
oClone . body . className += " DTFC_Cloned" ;
2016-04-22 00:37:33 +00:00
oClone . body . style . paddingBottom = dt . oScroll . iBarWidth + "px" ;
oClone . body . style . marginBottom = ( dt . oScroll . iBarWidth * 2 ) + "px" ; /* For IE */
2015-12-13 09:34:12 +00:00
if ( oClone . body . getAttribute ( 'id' ) !== null )
{
oClone . body . removeAttribute ( 'id' ) ;
}
$ ( '>thead>tr' , oClone . body ) . empty ( ) ;
$ ( '>tfoot' , oClone . body ) . remove ( ) ;
var nBody = $ ( 'tbody' , oClone . body ) [ 0 ] ;
$ ( nBody ) . empty ( ) ;
2016-04-22 00:37:33 +00:00
if ( dt . aiDisplay . length > 0 )
2015-12-13 09:34:12 +00:00
{
/ * C o p y t h e D a t a T a b l e s ' h e a d e r e l e m e n t s t o f o r c e t h e c o l u m n w i d t h i n e x a c t l y t h e
* same way that DataTables does it - have the header element , apply the width and
* colapse it down
* /
var nInnerThead = $ ( '>thead>tr' , oClone . body ) [ 0 ] ;
for ( iIndex = 0 ; iIndex < aiColumns . length ; iIndex ++ )
{
iColumn = aiColumns [ iIndex ] ;
2016-04-22 00:37:33 +00:00
nClone = $ ( dt . aoColumns [ iColumn ] . nTh ) . clone ( true ) [ 0 ] ;
2015-12-13 09:34:12 +00:00
nClone . innerHTML = "" ;
var oStyle = nClone . style ;
oStyle . paddingTop = "0" ;
oStyle . paddingBottom = "0" ;
oStyle . borderTopWidth = "0" ;
oStyle . borderBottomWidth = "0" ;
oStyle . height = 0 ;
oStyle . width = that . s . aiInnerWidths [ iColumn ] + "px" ;
nInnerThead . appendChild ( nClone ) ;
}
/* Add in the tbody elements, cloning form the master table */
$ ( '>tbody>tr' , that . dom . body ) . each ( function ( z ) {
var n = this . cloneNode ( false ) ;
n . removeAttribute ( 'id' ) ;
var i = that . s . dt . oFeatures . bServerSide === false ?
that . s . dt . aiDisplay [ that . s . dt . _iDisplayStart + z ] : z ;
2016-04-22 00:37:33 +00:00
var aTds = that . s . dt . aoData [ i ] . anCells || $ ( this ) . children ( 'td, th' ) ;
2015-12-13 09:34:12 +00:00
for ( iIndex = 0 ; iIndex < aiColumns . length ; iIndex ++ )
{
iColumn = aiColumns [ iIndex ] ;
if ( aTds . length > 0 )
{
nClone = $ ( aTds [ iColumn ] ) . clone ( true , true ) [ 0 ] ;
n . appendChild ( nClone ) ;
}
}
nBody . appendChild ( n ) ;
} ) ;
}
else
{
$ ( '>tbody>tr' , that . dom . body ) . each ( function ( z ) {
nClone = this . cloneNode ( true ) ;
nClone . className += ' DTFC_NoData' ;
$ ( 'td' , nClone ) . html ( '' ) ;
nBody . appendChild ( nClone ) ;
} ) ;
}
oClone . body . style . width = "100%" ;
oClone . body . style . margin = "0" ;
oClone . body . style . padding = "0" ;
2016-04-22 00:37:33 +00:00
// Interop with Scroller - need to use a height forcing element in the
// scrolling area in the same way that Scroller does in the body scroll.
if ( dt . oScroller !== undefined )
2015-12-13 09:34:12 +00:00
{
2016-04-22 00:37:33 +00:00
var scrollerForcer = dt . oScroller . dom . force ;
if ( ! oGrid . forcer ) {
oGrid . forcer = scrollerForcer . cloneNode ( true ) ;
oGrid . liner . appendChild ( oGrid . forcer ) ;
}
else {
oGrid . forcer . style . height = scrollerForcer . style . height ;
2015-12-13 09:34:12 +00:00
}
}
2016-04-22 00:37:33 +00:00
2015-12-13 09:34:12 +00:00
oGrid . liner . appendChild ( oClone . body ) ;
this . _fnEqualiseHeights ( 'tbody' , that . dom . body , oClone . body ) ;
/ *
* Footer
* /
2016-04-22 00:37:33 +00:00
if ( dt . nTFoot !== null )
2015-12-13 09:34:12 +00:00
{
if ( bAll )
{
if ( oClone . footer !== null )
{
oClone . footer . parentNode . removeChild ( oClone . footer ) ;
}
oClone . footer = $ ( this . dom . footer ) . clone ( true , true ) [ 0 ] ;
oClone . footer . className += " DTFC_Cloned" ;
oClone . footer . style . width = "100%" ;
oGrid . foot . appendChild ( oClone . footer ) ;
/* Copy the footer just like we do for the header */
2016-04-22 00:37:33 +00:00
aoCloneLayout = this . _fnCopyLayout ( dt . aoFooter , aiColumns ) ;
2015-12-13 09:34:12 +00:00
var jqCloneTfoot = $ ( '>tfoot' , oClone . footer ) ;
jqCloneTfoot . empty ( ) ;
for ( i = 0 , iLen = aoCloneLayout . length ; i < iLen ; i ++ )
{
jqCloneTfoot [ 0 ] . appendChild ( aoCloneLayout [ i ] . nTr ) ;
}
2016-04-22 00:37:33 +00:00
dt . oApi . _fnDrawHead ( dt , aoCloneLayout , true ) ;
2015-12-13 09:34:12 +00:00
}
else
{
2016-04-22 00:37:33 +00:00
aoCloneLayout = this . _fnCopyLayout ( dt . aoFooter , aiColumns ) ;
2015-12-13 09:34:12 +00:00
var aoCurrFooter = [ ] ;
2016-04-22 00:37:33 +00:00
dt . oApi . _fnDetectHeader ( aoCurrFooter , $ ( '>tfoot' , oClone . footer ) [ 0 ] ) ;
2015-12-13 09:34:12 +00:00
for ( i = 0 , iLen = aoCloneLayout . length ; i < iLen ; i ++ )
{
for ( j = 0 , jLen = aoCloneLayout [ i ] . length ; j < jLen ; j ++ )
{
aoCurrFooter [ i ] [ j ] . cell . className = aoCloneLayout [ i ] [ j ] . cell . className ;
}
}
}
this . _fnEqualiseHeights ( 'tfoot' , this . dom . footer , oClone . footer ) ;
}
/* Equalise the column widths between the header footer and body - body get's priority */
2016-04-22 00:37:33 +00:00
var anUnique = dt . oApi . _fnGetUniqueThs ( dt , $ ( '>thead' , oClone . header ) [ 0 ] ) ;
2015-12-13 09:34:12 +00:00
$ ( anUnique ) . each ( function ( i ) {
iColumn = aiColumns [ i ] ;
this . style . width = that . s . aiInnerWidths [ iColumn ] + "px" ;
} ) ;
if ( that . s . dt . nTFoot !== null )
{
2016-04-22 00:37:33 +00:00
anUnique = dt . oApi . _fnGetUniqueThs ( dt , $ ( '>tfoot' , oClone . footer ) [ 0 ] ) ;
2015-12-13 09:34:12 +00:00
$ ( anUnique ) . each ( function ( i ) {
iColumn = aiColumns [ i ] ;
this . style . width = that . s . aiInnerWidths [ iColumn ] + "px" ;
} ) ;
}
} ,
/ * *
* From a given table node ( THEAD etc ) , get a list of TR direct child elements
* @ param { Node } nIn Table element to search for TR elements ( THEAD , TBODY or TFOOT element )
* @ returns { Array } List of TR elements found
* @ private
* /
"_fnGetTrNodes" : function ( nIn )
{
var aOut = [ ] ;
for ( var i = 0 , iLen = nIn . childNodes . length ; i < iLen ; i ++ )
{
if ( nIn . childNodes [ i ] . nodeName . toUpperCase ( ) == "TR" )
{
aOut . push ( nIn . childNodes [ i ] ) ;
}
}
return aOut ;
} ,
/ * *
* Equalise the heights of the rows in a given table node in a cross browser way
* @ returns { void }
* @ param { String } nodeName Node type - thead , tbody or tfoot
* @ param { Node } original Original node to take the heights from
* @ param { Node } clone Copy the heights to
* @ private
* /
"_fnEqualiseHeights" : function ( nodeName , original , clone )
{
if ( this . s . sHeightMatch == 'none' && nodeName !== 'thead' && nodeName !== 'tfoot' )
{
return ;
}
var that = this ,
i , iLen , iHeight , iHeight2 , iHeightOriginal , iHeightClone ,
rootOriginal = original . getElementsByTagName ( nodeName ) [ 0 ] ,
rootClone = clone . getElementsByTagName ( nodeName ) [ 0 ] ,
jqBoxHack = $ ( '>' + nodeName + '>tr:eq(0)' , original ) . children ( ':first' ) ,
iBoxHack = jqBoxHack . outerHeight ( ) - jqBoxHack . height ( ) ,
anOriginal = this . _fnGetTrNodes ( rootOriginal ) ,
anClone = this . _fnGetTrNodes ( rootClone ) ,
heights = [ ] ;
for ( i = 0 , iLen = anClone . length ; i < iLen ; i ++ )
{
iHeightOriginal = anOriginal [ i ] . offsetHeight ;
iHeightClone = anClone [ i ] . offsetHeight ;
iHeight = iHeightClone > iHeightOriginal ? iHeightClone : iHeightOriginal ;
if ( this . s . sHeightMatch == 'semiauto' )
{
anOriginal [ i ] . _DTTC _iHeight = iHeight ;
}
heights . push ( iHeight ) ;
}
for ( i = 0 , iLen = anClone . length ; i < iLen ; i ++ )
{
anClone [ i ] . style . height = heights [ i ] + "px" ;
anOriginal [ i ] . style . height = heights [ i ] + "px" ;
}
}
} ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Statics
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* FixedColumns default settings for initialisation
* @ name FixedColumns . defaults
* @ namespace
* @ static
* /
FixedColumns . defaults = /** @lends FixedColumns.defaults */ {
/ * *
* Number of left hand columns to fix in position
* @ type int
* @ default 1
* @ static
* @ example
* var = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* new $ . fn . dataTable . fixedColumns ( table , {
* "leftColumns" : 2
* } ) ;
* /
"iLeftColumns" : 1 ,
/ * *
* Number of right hand columns to fix in position
* @ type int
* @ default 0
* @ static
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* new $ . fn . dataTable . fixedColumns ( table , {
* "rightColumns" : 1
* } ) ;
* /
"iRightColumns" : 0 ,
/ * *
* Draw callback function which is called when FixedColumns has redrawn the fixed assets
* @ type function ( object , object ) : void
* @ default null
* @ static
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* new $ . fn . dataTable . fixedColumns ( table , {
* "drawCallback" : function ( ) {
* alert ( "FixedColumns redraw" ) ;
* }
* } ) ;
* /
"fnDrawCallback" : null ,
/ * *
* Height matching algorthim to use . This can be "none" which will result in no height
* matching being applied by FixedColumns ( height matching could be forced by CSS in this
* case ) , "semiauto" whereby the height calculation will be performed once , and the result
* cached to be used again ( fnRecalculateHeight can be used to force recalculation ) , or
* "auto" when height matching is performed on every draw ( slowest but must accurate )
* @ type string
* @ default semiauto
* @ static
* @ example
* var table = $ ( '#example' ) . dataTable ( {
* "scrollX" : "100%"
* } ) ;
* new $ . fn . dataTable . fixedColumns ( table , {
* "heightMatch" : "auto"
* } ) ;
* /
"sHeightMatch" : "semiauto"
} ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constants
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* FixedColumns version
* @ name FixedColumns . version
* @ type String
* @ default See code
* @ static
* /
2016-04-22 00:37:33 +00:00
FixedColumns . version = "3.0.4" ;
2015-12-13 09:34:12 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fired events ( for documentation )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* Event fired whenever FixedColumns redraws the fixed columns ( i . e . clones the table elements from the main DataTable ) . This will occur whenever the DataTable that the FixedColumns instance is attached does its own draw .
* @ name FixedColumns # draw . dtfc
* @ event
* @ param { event } e jQuery event object
* @ param { object } o Event parameters from FixedColumns
* @ param { object } o . leftClone Instance 's object dom.clone.left for easy reference. This object contains references to the left fixed clumn column' s nodes
* @ param { object } o . rightClone Instance 's object dom.clone.right for easy reference. This object contains references to the right fixed clumn column' s nodes
* /
// Make FixedColumns accessible from the DataTables instance
$ . fn . dataTable . FixedColumns = FixedColumns ;
$ . fn . DataTable . FixedColumns = FixedColumns ;
return FixedColumns ;
} ; // /factory
// Define as an AMD module if possible
if ( typeof define === 'function' && define . amd ) {
define ( [ 'jquery' , 'datatables' ] , factory ) ;
}
else if ( typeof exports === 'object' ) {
// Node/CommonJS
factory ( require ( 'jquery' ) , require ( 'datatables' ) ) ;
}
else if ( jQuery && ! jQuery . fn . dataTable . FixedColumns ) {
// Otherwise simply initialise as normal, stopping multiple evaluation
factory ( jQuery , jQuery . fn . dataTable ) ;
}
} ) ( window , document ) ;