jquery-datatables-rails 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js +64 -29
- data/app/assets/javascripts/dataTables/extras/dataTables.autoFill.js +806 -648
- data/app/assets/javascripts/dataTables/extras/dataTables.buttons.js +1607 -0
- data/app/assets/javascripts/dataTables/extras/dataTables.colReorder.js +220 -267
- data/app/assets/javascripts/dataTables/extras/dataTables.fixedColumns.js +164 -69
- data/app/assets/javascripts/dataTables/extras/dataTables.fixedHeader.js +469 -870
- data/app/assets/javascripts/dataTables/extras/dataTables.keyTable.js +636 -972
- data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +472 -187
- data/app/assets/javascripts/dataTables/extras/dataTables.rowReorder.js +619 -0
- data/app/assets/javascripts/dataTables/extras/dataTables.scroller.js +146 -111
- data/app/assets/javascripts/dataTables/extras/dataTables.select.js +1038 -0
- data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnGetColumnData.js +0 -0
- data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnReloadAjax.js +0 -0
- data/app/assets/javascripts/dataTables/jquery.dataTables.foundation.js +37 -61
- data/app/assets/javascripts/dataTables/jquery.dataTables.js +720 -387
- data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.ipAddress.js +44 -0
- data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.numbersHtml.js +0 -0
- data/app/assets/javascripts/dataTables/jquery.dataTables.typeDetection.numbersHtml.js +0 -0
- data/app/assets/stylesheets/dataTables/jquery.dataTables.scss +34 -66
- data/app/assets/stylesheets/dataTables/src/demo_table.css +1 -1
- data/app/assets/stylesheets/dataTables/src/demo_table_jui.css.scss +4 -4
- data/lib/jquery/datatables/rails/version.rb +1 -1
- metadata +24 -19
@@ -1,11 +1,11 @@
|
|
1
|
-
/*! FixedColumns 3.0
|
1
|
+
/*! FixedColumns 3.2.0
|
2
2
|
* ©2010-2014 SpryMedia Ltd - datatables.net/license
|
3
3
|
*/
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @summary FixedColumns
|
7
7
|
* @description Freeze columns in place on a scrolling DataTable
|
8
|
-
* @version 3.0
|
8
|
+
* @version 3.2.0
|
9
9
|
* @file dataTables.fixedColumns.js
|
10
10
|
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
11
11
|
* @contact www.sprymedia.co.uk/contact
|
@@ -20,13 +20,35 @@
|
|
20
20
|
*
|
21
21
|
* For details please refer to: http://www.datatables.net
|
22
22
|
*/
|
23
|
+
(function( factory ){
|
24
|
+
if ( typeof define === 'function' && define.amd ) {
|
25
|
+
// AMD
|
26
|
+
define( ['jquery', 'datatables.net'], function ( $ ) {
|
27
|
+
return factory( $, window, document );
|
28
|
+
} );
|
29
|
+
}
|
30
|
+
else if ( typeof exports === 'object' ) {
|
31
|
+
// CommonJS
|
32
|
+
module.exports = function (root, $) {
|
33
|
+
if ( ! root ) {
|
34
|
+
root = window;
|
35
|
+
}
|
23
36
|
|
37
|
+
if ( ! $ || ! $.fn.dataTable ) {
|
38
|
+
$ = require('datatables.net')(root, $).$;
|
39
|
+
}
|
24
40
|
|
25
|
-
(
|
26
|
-
|
41
|
+
return factory( $, root, root.document );
|
42
|
+
};
|
43
|
+
}
|
44
|
+
else {
|
45
|
+
// Browser
|
46
|
+
factory( jQuery, window, document );
|
47
|
+
}
|
48
|
+
}(function( $, window, document, undefined ) {
|
49
|
+
'use strict';
|
50
|
+
var DataTable = $.fn.dataTable;
|
27
51
|
|
28
|
-
var factory = function( $, DataTable ) {
|
29
|
-
"use strict";
|
30
52
|
|
31
53
|
/**
|
32
54
|
* When making use of DataTables' x-axis scrolling feature, you may wish to
|
@@ -62,14 +84,12 @@ var FixedColumns = function ( dt, init ) {
|
|
62
84
|
var that = this;
|
63
85
|
|
64
86
|
/* Sanity check - you just know it will happen */
|
65
|
-
if ( ! ( this instanceof FixedColumns ) )
|
66
|
-
{
|
87
|
+
if ( ! ( this instanceof FixedColumns ) ) {
|
67
88
|
alert( "FixedColumns warning: FixedColumns must be initialised with the 'new' keyword." );
|
68
89
|
return;
|
69
90
|
}
|
70
91
|
|
71
|
-
if (
|
72
|
-
{
|
92
|
+
if ( init === undefined || init === true ) {
|
73
93
|
init = {};
|
74
94
|
}
|
75
95
|
|
@@ -82,9 +102,7 @@ var FixedColumns = function ( dt, init ) {
|
|
82
102
|
}
|
83
103
|
|
84
104
|
// v1.10 allows the settings object to be got form a number of sources
|
85
|
-
var dtSettings = $.fn.dataTable.Api
|
86
|
-
new $.fn.dataTable.Api( dt ).settings()[0] :
|
87
|
-
dt.fnSettings();
|
105
|
+
var dtSettings = new $.fn.dataTable.Api( dt ).settings()[0];
|
88
106
|
|
89
107
|
/**
|
90
108
|
* Settings object which contains customisable information for FixedColumns instance
|
@@ -265,6 +283,10 @@ var FixedColumns = function ( dt, init ) {
|
|
265
283
|
}
|
266
284
|
};
|
267
285
|
|
286
|
+
if ( dtSettings._oFixedColumns ) {
|
287
|
+
throw 'FixedColumns already initialised on this table';
|
288
|
+
}
|
289
|
+
|
268
290
|
/* Attach the instance to the DataTables instance so it can be accessed easily */
|
269
291
|
dtSettings._oFixedColumns = this;
|
270
292
|
|
@@ -283,7 +305,7 @@ var FixedColumns = function ( dt, init ) {
|
|
283
305
|
|
284
306
|
|
285
307
|
|
286
|
-
FixedColumns.prototype
|
308
|
+
$.extend( FixedColumns.prototype , {
|
287
309
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
288
310
|
* Public methods
|
289
311
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
@@ -474,7 +496,11 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
474
496
|
.on( 'mouseover.DTFC touchstart.DTFC', function () {
|
475
497
|
mouseController = 'main';
|
476
498
|
} )
|
477
|
-
.on( 'scroll.DTFC', function () {
|
499
|
+
.on( 'scroll.DTFC', function (e) {
|
500
|
+
if ( ! mouseController && e.originalEvent ) {
|
501
|
+
mouseController = 'main';
|
502
|
+
}
|
503
|
+
|
478
504
|
if ( mouseController === 'main' ) {
|
479
505
|
if ( that.s.iLeftColumns > 0 ) {
|
480
506
|
that.dom.grid.left.liner.scrollTop = that.dom.scroller.scrollTop;
|
@@ -495,7 +521,11 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
495
521
|
.on( 'mouseover.DTFC touchstart.DTFC', function () {
|
496
522
|
mouseController = 'left';
|
497
523
|
} )
|
498
|
-
.on( 'scroll.DTFC', function () {
|
524
|
+
.on( 'scroll.DTFC', function ( e ) {
|
525
|
+
if ( ! mouseController && e.originalEvent ) {
|
526
|
+
mouseController = 'left';
|
527
|
+
}
|
528
|
+
|
499
529
|
if ( mouseController === 'left' ) {
|
500
530
|
that.dom.scroller.scrollTop = that.dom.grid.left.liner.scrollTop;
|
501
531
|
if ( that.s.iRightColumns > 0 ) {
|
@@ -503,7 +533,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
503
533
|
}
|
504
534
|
}
|
505
535
|
} )
|
506
|
-
.on( wheelType, function(e) {
|
536
|
+
.on( wheelType, function(e) {
|
507
537
|
// Pass horizontal scrolling through
|
508
538
|
var xDelta = e.type === 'wheel' ?
|
509
539
|
-e.originalEvent.deltaX :
|
@@ -518,7 +548,11 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
518
548
|
.on( 'mouseover.DTFC touchstart.DTFC', function () {
|
519
549
|
mouseController = 'right';
|
520
550
|
} )
|
521
|
-
.on( 'scroll.DTFC', function () {
|
551
|
+
.on( 'scroll.DTFC', function ( e ) {
|
552
|
+
if ( ! mouseController && e.originalEvent ) {
|
553
|
+
mouseController = 'right';
|
554
|
+
}
|
555
|
+
|
522
556
|
if ( mouseController === 'right' ) {
|
523
557
|
that.dom.scroller.scrollTop = that.dom.grid.right.liner.scrollTop;
|
524
558
|
if ( that.s.iLeftColumns > 0 ) {
|
@@ -551,21 +585,23 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
551
585
|
that._fnColCalc();
|
552
586
|
that._fnGridLayout( that );
|
553
587
|
} )
|
554
|
-
.on( 'column-visibility.dt.DTFC', function () {
|
555
|
-
|
556
|
-
|
557
|
-
|
588
|
+
.on( 'column-visibility.dt.DTFC', function ( e, settings, column, vis, recalc ) {
|
589
|
+
if ( recalc === undefined || recalc ) {
|
590
|
+
that._fnColCalc();
|
591
|
+
that._fnGridLayout( that );
|
592
|
+
that._fnDraw( true );
|
593
|
+
}
|
558
594
|
} )
|
559
595
|
.on( 'destroy.dt.DTFC', function () {
|
560
|
-
jqTable.off( 'column-sizing.dt.DTFC destroy.dt.DTFC draw.dt.DTFC' );
|
596
|
+
jqTable.off( 'column-sizing.dt.DTFC column-visibility.dt.DTFC destroy.dt.DTFC draw.dt.DTFC' );
|
561
597
|
|
562
|
-
$(that.dom.scroller).off( '
|
598
|
+
$(that.dom.scroller).off( 'mouseover.DTFC touchstart.DTFC scroll.DTFC' );
|
563
599
|
$(window).off( 'resize.DTFC' );
|
564
600
|
|
565
|
-
$(that.dom.grid.left.liner).off( '
|
601
|
+
$(that.dom.grid.left.liner).off( 'mouseover.DTFC touchstart.DTFC scroll.DTFC '+wheelType );
|
566
602
|
$(that.dom.grid.left.wrapper).remove();
|
567
603
|
|
568
|
-
$(that.dom.grid.right.liner).off( '
|
604
|
+
$(that.dom.grid.right.liner).off( 'mouseover.DTFC touchstart.DTFC scroll.DTFC '+wheelType );
|
569
605
|
$(that.dom.grid.right.wrapper).remove();
|
570
606
|
} );
|
571
607
|
|
@@ -922,9 +958,10 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
922
958
|
* @returns {Array} Copy of the layout array
|
923
959
|
* @param {Object} aoOriginal Layout array from DataTables (aoHeader or aoFooter)
|
924
960
|
* @param {Object} aiColumns Columns to copy
|
961
|
+
* @param {boolean} events Copy cell events or not
|
925
962
|
* @private
|
926
963
|
*/
|
927
|
-
"_fnCopyLayout": function ( aoOriginal, aiColumns )
|
964
|
+
"_fnCopyLayout": function ( aoOriginal, aiColumns, events )
|
928
965
|
{
|
929
966
|
var aReturn = [];
|
930
967
|
var aClones = [];
|
@@ -933,7 +970,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
933
970
|
for ( var i=0, iLen=aoOriginal.length ; i<iLen ; i++ )
|
934
971
|
{
|
935
972
|
var aRow = [];
|
936
|
-
aRow.nTr = $(aoOriginal[i].nTr).clone(
|
973
|
+
aRow.nTr = $(aoOriginal[i].nTr).clone(events, false)[0];
|
937
974
|
|
938
975
|
for ( var j=0, jLen=this.s.iTableColumns ; j<jLen ; j++ )
|
939
976
|
{
|
@@ -945,7 +982,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
945
982
|
var iCloned = $.inArray( aoOriginal[i][j].cell, aCloned );
|
946
983
|
if ( iCloned === -1 )
|
947
984
|
{
|
948
|
-
var nClone = $(aoOriginal[i][j].cell).clone(
|
985
|
+
var nClone = $(aoOriginal[i][j].cell).clone(events, false)[0];
|
949
986
|
aClones.push( nClone );
|
950
987
|
aCloned.push( aoOriginal[i][j].cell );
|
951
988
|
|
@@ -992,17 +1029,15 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
992
1029
|
*/
|
993
1030
|
if ( bAll )
|
994
1031
|
{
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
}
|
999
|
-
oClone.header = $(this.dom.header).clone(true, true)[0];
|
1032
|
+
$(oClone.header).remove();
|
1033
|
+
|
1034
|
+
oClone.header = $(this.dom.header).clone(true, false)[0];
|
1000
1035
|
oClone.header.className += " DTFC_Cloned";
|
1001
1036
|
oClone.header.style.width = "100%";
|
1002
1037
|
oGrid.head.appendChild( oClone.header );
|
1003
1038
|
|
1004
1039
|
/* Copy the DataTables layout cache for the header for our floating column */
|
1005
|
-
aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns );
|
1040
|
+
aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns, true );
|
1006
1041
|
jqCloneThead = $('>thead', oClone.header);
|
1007
1042
|
jqCloneThead.empty();
|
1008
1043
|
|
@@ -1024,7 +1059,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
1024
1059
|
* cloned cells, just copy the classes across. To get the matching layout for the
|
1025
1060
|
* fixed component, we use the DataTables _fnDetectHeader method, allowing 1:1 mapping
|
1026
1061
|
*/
|
1027
|
-
aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns );
|
1062
|
+
aoCloneLayout = this._fnCopyLayout( dt.aoHeader, aiColumns, false );
|
1028
1063
|
aoFixedHeader=[];
|
1029
1064
|
|
1030
1065
|
dt.oApi._fnDetectHeader( aoFixedHeader, $('>thead', oClone.header)[0] );
|
@@ -1055,7 +1090,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
1055
1090
|
|
1056
1091
|
if ( oClone.body !== null )
|
1057
1092
|
{
|
1058
|
-
oClone.body.
|
1093
|
+
$(oClone.body).remove();
|
1059
1094
|
oClone.body = null;
|
1060
1095
|
}
|
1061
1096
|
|
@@ -1169,7 +1204,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
1169
1204
|
oGrid.foot.appendChild( oClone.footer );
|
1170
1205
|
|
1171
1206
|
/* Copy the footer just like we do for the header */
|
1172
|
-
aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns );
|
1207
|
+
aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns, true );
|
1173
1208
|
var jqCloneTfoot = $('>tfoot', oClone.footer);
|
1174
1209
|
jqCloneTfoot.empty();
|
1175
1210
|
|
@@ -1181,7 +1216,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
1181
1216
|
}
|
1182
1217
|
else
|
1183
1218
|
{
|
1184
|
-
aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns );
|
1219
|
+
aoCloneLayout = this._fnCopyLayout( dt.aoFooter, aiColumns, false );
|
1185
1220
|
var aoCurrFooter=[];
|
1186
1221
|
|
1187
1222
|
dt.oApi._fnDetectHeader( aoCurrFooter, $('>tfoot', oClone.footer)[0] );
|
@@ -1280,7 +1315,7 @@ FixedColumns.prototype = /** @lends FixedColumns.prototype */{
|
|
1280
1315
|
anOriginal[i].style.height = heights[i]+"px";
|
1281
1316
|
}
|
1282
1317
|
}
|
1283
|
-
};
|
1318
|
+
} );
|
1284
1319
|
|
1285
1320
|
|
1286
1321
|
|
@@ -1376,48 +1411,108 @@ FixedColumns.defaults = /** @lends FixedColumns.defaults */{
|
|
1376
1411
|
* @default See code
|
1377
1412
|
* @static
|
1378
1413
|
*/
|
1379
|
-
FixedColumns.version = "3.0
|
1414
|
+
FixedColumns.version = "3.2.0";
|
1380
1415
|
|
1381
1416
|
|
1382
1417
|
|
1383
1418
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
1384
|
-
*
|
1419
|
+
* DataTables API integration
|
1385
1420
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
1386
1421
|
|
1422
|
+
DataTable.Api.register( 'fixedColumns()', function () {
|
1423
|
+
return this;
|
1424
|
+
} );
|
1387
1425
|
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
* @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
|
1396
|
-
*/
|
1426
|
+
DataTable.Api.register( 'fixedColumns().update()', function () {
|
1427
|
+
return this.iterator( 'table', function ( ctx ) {
|
1428
|
+
if ( ctx._oFixedColumns ) {
|
1429
|
+
ctx._oFixedColumns.fnUpdate();
|
1430
|
+
}
|
1431
|
+
} );
|
1432
|
+
} );
|
1397
1433
|
|
1434
|
+
DataTable.Api.register( 'fixedColumns().relayout()', function () {
|
1435
|
+
return this.iterator( 'table', function ( ctx ) {
|
1436
|
+
if ( ctx._oFixedColumns ) {
|
1437
|
+
ctx._oFixedColumns.fnRedrawLayout();
|
1438
|
+
}
|
1439
|
+
} );
|
1440
|
+
} );
|
1398
1441
|
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1442
|
+
DataTable.Api.register( 'rows().recalcHeight()', function () {
|
1443
|
+
return this.iterator( 'row', function ( ctx, idx ) {
|
1444
|
+
if ( ctx._oFixedColumns ) {
|
1445
|
+
ctx._oFixedColumns.fnRecalculateHeight( this.row(idx).node() );
|
1446
|
+
}
|
1447
|
+
} );
|
1448
|
+
} );
|
1449
|
+
|
1450
|
+
DataTable.Api.register( 'fixedColumns().rowIndex()', function ( row ) {
|
1451
|
+
row = $(row);
|
1452
|
+
|
1453
|
+
return row.parents('.DTFC_Cloned').length ?
|
1454
|
+
this.rows( { page: 'current' } ).indexes()[ row.index() ] :
|
1455
|
+
this.row( row ).index();
|
1456
|
+
} );
|
1457
|
+
|
1458
|
+
DataTable.Api.register( 'fixedColumns().cellIndex()', function ( cell ) {
|
1459
|
+
cell = $(cell);
|
1460
|
+
|
1461
|
+
if ( cell.parents('.DTFC_Cloned').length ) {
|
1462
|
+
var rowClonedIdx = cell.parent().index();
|
1463
|
+
var rowIdx = this.rows( { page: 'current' } ).indexes()[ rowClonedIdx ];
|
1464
|
+
var columnIdx;
|
1465
|
+
|
1466
|
+
if ( cell.parents('.DTFC_LeftWrapper').length ) {
|
1467
|
+
columnIdx = cell.index();
|
1468
|
+
}
|
1469
|
+
else {
|
1470
|
+
var columns = this.columns().flatten().length;
|
1471
|
+
columnIdx = columns - this.context[0]._oFixedColumns.s.iRightColumns + cell.index();
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
return {
|
1475
|
+
row: rowIdx,
|
1476
|
+
column: this.column.index( 'toData', columnIdx ),
|
1477
|
+
columnVisible: columnIdx
|
1478
|
+
};
|
1479
|
+
}
|
1480
|
+
else {
|
1481
|
+
return this.cell( cell ).index();
|
1482
|
+
}
|
1483
|
+
} );
|
1402
1484
|
|
1403
1485
|
|
1404
|
-
return FixedColumns;
|
1405
|
-
}; // /factory
|
1406
1486
|
|
1407
1487
|
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1488
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
1489
|
+
* Initialisation
|
1490
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
1491
|
+
|
1492
|
+
// Attach a listener to the document which listens for DataTables initialisation
|
1493
|
+
// events so we can automatically initialise
|
1494
|
+
$(document).on( 'init.dt.fixedColumns', function (e, settings) {
|
1495
|
+
if ( e.namespace !== 'dt' ) {
|
1496
|
+
return;
|
1497
|
+
}
|
1498
|
+
|
1499
|
+
var init = settings.oInit.fixedColumns;
|
1500
|
+
var defaults = DataTable.defaults.fixedColumns;
|
1420
1501
|
|
1502
|
+
if ( init || defaults ) {
|
1503
|
+
var opts = $.extend( {}, init, defaults );
|
1421
1504
|
|
1422
|
-
|
1505
|
+
if ( init !== false ) {
|
1506
|
+
new FixedColumns( settings, opts );
|
1507
|
+
}
|
1508
|
+
}
|
1509
|
+
} );
|
1423
1510
|
|
1511
|
+
|
1512
|
+
|
1513
|
+
// Make FixedColumns accessible from the DataTables instance
|
1514
|
+
$.fn.dataTable.FixedColumns = FixedColumns;
|
1515
|
+
$.fn.DataTable.FixedColumns = FixedColumns;
|
1516
|
+
|
1517
|
+
return FixedColumns;
|
1518
|
+
}));
|
@@ -1,16 +1,16 @@
|
|
1
|
-
/*! FixedHeader
|
2
|
-
* ©
|
1
|
+
/*! FixedHeader 3.1.0
|
2
|
+
* ©2009-2015 SpryMedia Ltd - datatables.net/license
|
3
3
|
*/
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @summary FixedHeader
|
7
7
|
* @description Fix a table's header or footer, so it is always visible while
|
8
|
-
*
|
9
|
-
* @version
|
8
|
+
* scrolling
|
9
|
+
* @version 3.1.0
|
10
10
|
* @file dataTables.fixedHeader.js
|
11
11
|
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
12
12
|
* @contact www.sprymedia.co.uk/contact
|
13
|
-
* @copyright Copyright 2009-
|
13
|
+
* @copyright Copyright 2009-2015 SpryMedia Ltd.
|
14
14
|
*
|
15
15
|
* This source file is free software, available under the following license:
|
16
16
|
* MIT license - http://datatables.net/license/mit
|
@@ -22,125 +22,106 @@
|
|
22
22
|
* For details please refer to: http://www.datatables.net
|
23
23
|
*/
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
(function( factory ){
|
26
|
+
if ( typeof define === 'function' && define.amd ) {
|
27
|
+
// AMD
|
28
|
+
define( ['jquery', 'datatables.net'], function ( $ ) {
|
29
|
+
return factory( $, window, document );
|
30
|
+
} );
|
31
|
+
}
|
32
|
+
else if ( typeof exports === 'object' ) {
|
33
|
+
// CommonJS
|
34
|
+
module.exports = function (root, $) {
|
35
|
+
if ( ! root ) {
|
36
|
+
root = window;
|
37
|
+
}
|
28
38
|
|
29
|
-
|
30
|
-
|
39
|
+
if ( ! $ || ! $.fn.dataTable ) {
|
40
|
+
$ = require('datatables.net')(root, $).$;
|
41
|
+
}
|
31
42
|
|
32
|
-
(
|
43
|
+
return factory( $, root, root.document );
|
44
|
+
};
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
// Browser
|
48
|
+
factory( jQuery, window, document );
|
49
|
+
}
|
50
|
+
}(function( $, window, document, undefined ) {
|
51
|
+
'use strict';
|
52
|
+
var DataTable = $.fn.dataTable;
|
33
53
|
|
34
54
|
|
35
|
-
var
|
36
|
-
"use strict";
|
55
|
+
var _instCounter = 0;
|
37
56
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
* Inputs: mixed:mTable - target table
|
43
|
-
* @param {object} dt DataTables instance or HTML table node. With DataTables
|
44
|
-
* 1.10 this can also be a jQuery collection (with just a single table in its
|
45
|
-
* result set), a jQuery selector, DataTables API instance or settings
|
46
|
-
* object.
|
47
|
-
* @param {object} [oInit] initialisation settings, with the following
|
48
|
-
* properties (each optional)
|
49
|
-
* * bool:top - fix the header (default true)
|
50
|
-
* * bool:bottom - fix the footer (default false)
|
51
|
-
* * int:left - fix the left column(s) (default 0)
|
52
|
-
* * int:right - fix the right column(s) (default 0)
|
53
|
-
* * int:zTop - fixed header zIndex
|
54
|
-
* * int:zBottom - fixed footer zIndex
|
55
|
-
* * int:zLeft - fixed left zIndex
|
56
|
-
* * int:zRight - fixed right zIndex
|
57
|
-
*/
|
58
|
-
FixedHeader = function ( mTable, oInit ) {
|
59
|
-
/* Sanity check - you just know it will happen */
|
60
|
-
if ( ! this instanceof FixedHeader )
|
61
|
-
{
|
62
|
-
alert( "FixedHeader warning: FixedHeader must be initialised with the 'new' keyword." );
|
63
|
-
return;
|
57
|
+
var FixedHeader = function ( dt, config ) {
|
58
|
+
// Sanity check - you just know it will happen
|
59
|
+
if ( ! (this instanceof FixedHeader) ) {
|
60
|
+
throw "FixedHeader must be initialised with the 'new' keyword.";
|
64
61
|
}
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
"iTableWidth": 0,
|
89
|
-
"iTableHeight": 0,
|
90
|
-
"iTableLeft": 0,
|
91
|
-
"iTableRight": 0, /* note this is left+width, not actually "right" */
|
92
|
-
"iTableTop": 0,
|
93
|
-
"iTableBottom": 0 /* note this is top+height, not actually "bottom" */
|
63
|
+
// Allow a boolean true for defaults
|
64
|
+
if ( config === true ) {
|
65
|
+
config = {};
|
66
|
+
}
|
67
|
+
|
68
|
+
dt = new DataTable.Api( dt );
|
69
|
+
|
70
|
+
this.c = $.extend( true, {}, FixedHeader.defaults, config );
|
71
|
+
|
72
|
+
this.s = {
|
73
|
+
dt: dt,
|
74
|
+
position: {
|
75
|
+
theadTop: 0,
|
76
|
+
tbodyTop: 0,
|
77
|
+
tfootTop: 0,
|
78
|
+
tfootBottom: 0,
|
79
|
+
width: 0,
|
80
|
+
left: 0,
|
81
|
+
tfootHeight: 0,
|
82
|
+
theadHeight: 0,
|
83
|
+
windowHeight: $(window).height(),
|
84
|
+
visible: true
|
94
85
|
},
|
95
|
-
|
96
|
-
|
86
|
+
headerMode: null,
|
87
|
+
footerMode: null,
|
88
|
+
autoWidth: dt.settings()[0].oFeatures.bAutoWidth,
|
89
|
+
namespace: '.dtfc'+(_instCounter++),
|
90
|
+
scrollLeft: {
|
91
|
+
header: -1,
|
92
|
+
footer: -1
|
97
93
|
},
|
98
|
-
|
99
|
-
"bFooter": false,
|
100
|
-
"bInitComplete": false
|
101
|
-
};
|
102
|
-
|
103
|
-
/*
|
104
|
-
* Function: fnGetSettings
|
105
|
-
* Purpose: Get the settings for this object
|
106
|
-
* Returns: object: - settings object
|
107
|
-
* Inputs: -
|
108
|
-
*/
|
109
|
-
this.fnGetSettings = function () {
|
110
|
-
return oSettings;
|
111
|
-
};
|
112
|
-
|
113
|
-
/*
|
114
|
-
* Function: fnUpdate
|
115
|
-
* Purpose: Update the positioning and copies of the fixed elements
|
116
|
-
* Returns: -
|
117
|
-
* Inputs: -
|
118
|
-
*/
|
119
|
-
this.fnUpdate = function () {
|
120
|
-
this._fnUpdateClones();
|
121
|
-
this._fnUpdatePositions();
|
94
|
+
enable: true
|
122
95
|
};
|
123
96
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
97
|
+
this.dom = {
|
98
|
+
floatingHeader: null,
|
99
|
+
thead: $(dt.table().header()),
|
100
|
+
tbody: $(dt.table().body()),
|
101
|
+
tfoot: $(dt.table().footer()),
|
102
|
+
header: {
|
103
|
+
host: null,
|
104
|
+
floating: null,
|
105
|
+
placeholder: null
|
106
|
+
},
|
107
|
+
footer: {
|
108
|
+
host: null,
|
109
|
+
floating: null,
|
110
|
+
placeholder: null
|
111
|
+
}
|
132
112
|
};
|
133
113
|
|
114
|
+
this.dom.header.host = this.dom.thead.parent();
|
115
|
+
this.dom.footer.host = this.dom.tfoot.parent();
|
134
116
|
|
135
|
-
var
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
dt._oPluginFixedHeader = this;
|
117
|
+
var dtSettings = dt.settings()[0];
|
118
|
+
if ( dtSettings._fixedHeader ) {
|
119
|
+
throw "FixedHeader already initialised on table "+dtSettings.nTable.id;
|
120
|
+
}
|
140
121
|
|
141
|
-
|
142
|
-
this.fnInit( dt, oInit );
|
122
|
+
dtSettings._fixedHeader = this;
|
143
123
|
|
124
|
+
this._constructor();
|
144
125
|
};
|
145
126
|
|
146
127
|
|
@@ -149,880 +130,498 @@ FixedHeader = function ( mTable, oInit ) {
|
|
149
130
|
* Purpose: Prototype for FixedHeader
|
150
131
|
* Scope: global
|
151
132
|
*/
|
152
|
-
FixedHeader.prototype
|
153
|
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
154
|
-
*
|
133
|
+
$.extend( FixedHeader.prototype, {
|
134
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
135
|
+
* API methods
|
155
136
|
*/
|
156
|
-
|
157
|
-
|
158
|
-
*
|
159
|
-
*
|
160
|
-
*
|
161
|
-
* Inputs: {as FixedHeader function}
|
137
|
+
|
138
|
+
/**
|
139
|
+
* Enable / disable the fixed elements
|
140
|
+
*
|
141
|
+
* @param {boolean} enable `true` to enable, `false` to disable
|
162
142
|
*/
|
163
|
-
|
143
|
+
enable: function ( enable )
|
164
144
|
{
|
165
|
-
|
166
|
-
var that = this;
|
167
|
-
|
168
|
-
/* Record the user definable settings */
|
169
|
-
this.fnInitSettings( s, oInit );
|
145
|
+
this.s.enable = enable;
|
170
146
|
|
171
|
-
if (
|
172
|
-
|
173
|
-
alert( "FixedHeader 2 is not supported with DataTables' scrolling mode at this time" );
|
174
|
-
return;
|
147
|
+
if ( this.c.header ) {
|
148
|
+
this._modeChange( 'in-place', 'header', true );
|
175
149
|
}
|
176
150
|
|
177
|
-
|
178
|
-
|
179
|
-
"fn": function () {
|
180
|
-
FixedHeader.fnMeasure();
|
181
|
-
that._fnUpdateClones.call(that);
|
182
|
-
that._fnUpdatePositions.call(that);
|
183
|
-
},
|
184
|
-
"sName": "FixedHeader"
|
185
|
-
} );
|
186
|
-
|
187
|
-
s.bFooter = ($('>tfoot', s.nTable).length > 0) ? true : false;
|
188
|
-
|
189
|
-
/* Add the 'sides' that are fixed */
|
190
|
-
if ( s.oSides.top )
|
191
|
-
{
|
192
|
-
s.aoCache.push( that._fnCloneTable( "fixedHeader", "FixedHeader_Header", that._fnCloneThead ) );
|
193
|
-
}
|
194
|
-
if ( s.oSides.bottom )
|
195
|
-
{
|
196
|
-
s.aoCache.push( that._fnCloneTable( "fixedFooter", "FixedHeader_Footer", that._fnCloneTfoot ) );
|
197
|
-
}
|
198
|
-
if ( s.oSides.left )
|
199
|
-
{
|
200
|
-
s.aoCache.push( that._fnCloneTable( "fixedLeft", "FixedHeader_Left", that._fnCloneTLeft, s.oSides.left ) );
|
151
|
+
if ( this.c.footer && this.dom.tfoot.length ) {
|
152
|
+
this._modeChange( 'in-place', 'footer', true );
|
201
153
|
}
|
202
|
-
if ( s.oSides.right )
|
203
|
-
{
|
204
|
-
s.aoCache.push( that._fnCloneTable( "fixedRight", "FixedHeader_Right", that._fnCloneTRight, s.oSides.right ) );
|
205
|
-
}
|
206
|
-
|
207
|
-
/* Event listeners for window movement */
|
208
|
-
FixedHeader.afnScroll.push( function () {
|
209
|
-
that._fnUpdatePositions.call(that);
|
210
|
-
} );
|
211
154
|
|
212
|
-
|
213
|
-
FixedHeader.fnMeasure();
|
214
|
-
that._fnUpdateClones.call(that);
|
215
|
-
that._fnUpdatePositions.call(that);
|
216
|
-
} );
|
217
|
-
|
218
|
-
$(s.nTable)
|
219
|
-
.on('column-reorder.dt', function () {
|
220
|
-
FixedHeader.fnMeasure();
|
221
|
-
that._fnUpdateClones( true );
|
222
|
-
that._fnUpdatePositions();
|
223
|
-
} )
|
224
|
-
.on('column-visibility.dt', function () {
|
225
|
-
FixedHeader.fnMeasure();
|
226
|
-
that._fnUpdateClones( true );
|
227
|
-
that._fnUpdatePositions();
|
228
|
-
} );
|
229
|
-
|
230
|
-
/* Get things right to start with */
|
231
|
-
FixedHeader.fnMeasure();
|
232
|
-
that._fnUpdateClones();
|
233
|
-
that._fnUpdatePositions();
|
234
|
-
|
235
|
-
s.bInitComplete = true;
|
155
|
+
this.update();
|
236
156
|
},
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
*
|
241
|
-
|
242
|
-
|
243
|
-
/*
|
244
|
-
* Function: fnInitSettings
|
245
|
-
* Purpose: Take the user's settings and copy them to our local store
|
246
|
-
* Returns: -
|
247
|
-
* Inputs: object:s - the local settings object
|
248
|
-
* object:oInit - the user's settings object
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Set header offset
|
160
|
+
*
|
161
|
+
* @param {int} new value for headerOffset
|
249
162
|
*/
|
250
|
-
|
163
|
+
headerOffset: function ( offset )
|
251
164
|
{
|
252
|
-
if (
|
253
|
-
|
254
|
-
|
255
|
-
s.oSides.top = oInit.top;
|
256
|
-
}
|
257
|
-
if ( oInit.bottom !== undefined ) {
|
258
|
-
s.oSides.bottom = oInit.bottom;
|
259
|
-
}
|
260
|
-
if ( typeof oInit.left == 'boolean' ) {
|
261
|
-
s.oSides.left = oInit.left ? 1 : 0;
|
262
|
-
}
|
263
|
-
else if ( oInit.left !== undefined ) {
|
264
|
-
s.oSides.left = oInit.left;
|
265
|
-
}
|
266
|
-
if ( typeof oInit.right == 'boolean' ) {
|
267
|
-
s.oSides.right = oInit.right ? 1 : 0;
|
268
|
-
}
|
269
|
-
else if ( oInit.right !== undefined ) {
|
270
|
-
s.oSides.right = oInit.right;
|
271
|
-
}
|
272
|
-
|
273
|
-
if ( oInit.zTop !== undefined ) {
|
274
|
-
s.oZIndexes.top = oInit.zTop;
|
275
|
-
}
|
276
|
-
if ( oInit.zBottom !== undefined ) {
|
277
|
-
s.oZIndexes.bottom = oInit.zBottom;
|
278
|
-
}
|
279
|
-
if ( oInit.zLeft !== undefined ) {
|
280
|
-
s.oZIndexes.left = oInit.zLeft;
|
281
|
-
}
|
282
|
-
if ( oInit.zRight !== undefined ) {
|
283
|
-
s.oZIndexes.right = oInit.zRight;
|
284
|
-
}
|
285
|
-
|
286
|
-
if ( oInit.offsetTop !== undefined ) {
|
287
|
-
s.oOffset.top = oInit.offsetTop;
|
288
|
-
}
|
289
|
-
if ( oInit.alwaysCloneTop !== undefined ) {
|
290
|
-
s.oCloneOnDraw.top = oInit.alwaysCloneTop;
|
291
|
-
}
|
292
|
-
if ( oInit.alwaysCloneBottom !== undefined ) {
|
293
|
-
s.oCloneOnDraw.bottom = oInit.alwaysCloneBottom;
|
294
|
-
}
|
295
|
-
if ( oInit.alwaysCloneLeft !== undefined ) {
|
296
|
-
s.oCloneOnDraw.left = oInit.alwaysCloneLeft;
|
297
|
-
}
|
298
|
-
if ( oInit.alwaysCloneRight !== undefined ) {
|
299
|
-
s.oCloneOnDraw.right = oInit.alwaysCloneRight;
|
300
|
-
}
|
165
|
+
if ( offset !== undefined ) {
|
166
|
+
this.c.headerOffset = offset;
|
167
|
+
this.update();
|
301
168
|
}
|
302
|
-
},
|
303
169
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
*
|
170
|
+
return this.c.headerOffset;
|
171
|
+
},
|
172
|
+
|
173
|
+
/**
|
174
|
+
* Set footer offset
|
175
|
+
*
|
176
|
+
* @param {int} new value for footerOffset
|
309
177
|
*/
|
310
|
-
|
178
|
+
footerOffset: function ( offset )
|
311
179
|
{
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
/* We know that the table _MUST_ has a DIV wrapped around it, because this is simply how
|
316
|
-
* DataTables works. Therefore, we can set this to be relatively position (if it is not
|
317
|
-
* alreadu absolute, and use this as the base point for the cloned header
|
318
|
-
*/
|
319
|
-
if ( $(s.nTable.parentNode).css('position') != "absolute" )
|
320
|
-
{
|
321
|
-
s.nTable.parentNode.style.position = "relative";
|
322
|
-
}
|
323
|
-
|
324
|
-
/* Just a shallow clone will do - we only want the table node */
|
325
|
-
nCTable = s.nTable.cloneNode( false );
|
326
|
-
nCTable.removeAttribute( 'id' );
|
327
|
-
|
328
|
-
var nDiv = document.createElement( 'div' );
|
329
|
-
nDiv.style.position = "absolute";
|
330
|
-
nDiv.style.top = "0px";
|
331
|
-
nDiv.style.left = "0px";
|
332
|
-
nDiv.className += " FixedHeader_Cloned "+sType+" "+sClass;
|
333
|
-
|
334
|
-
/* Set the zIndexes */
|
335
|
-
if ( sType == "fixedHeader" )
|
336
|
-
{
|
337
|
-
nDiv.style.zIndex = s.oZIndexes.top;
|
338
|
-
}
|
339
|
-
if ( sType == "fixedFooter" )
|
340
|
-
{
|
341
|
-
nDiv.style.zIndex = s.oZIndexes.bottom;
|
342
|
-
}
|
343
|
-
if ( sType == "fixedLeft" )
|
344
|
-
{
|
345
|
-
nDiv.style.zIndex = s.oZIndexes.left;
|
346
|
-
}
|
347
|
-
else if ( sType == "fixedRight" )
|
348
|
-
{
|
349
|
-
nDiv.style.zIndex = s.oZIndexes.right;
|
180
|
+
if ( offset !== undefined ) {
|
181
|
+
this.c.footerOffset = offset;
|
182
|
+
this.update();
|
350
183
|
}
|
351
184
|
|
352
|
-
|
353
|
-
nCTable.style.margin = "0";
|
354
|
-
|
355
|
-
/* Insert the newly cloned table into the DOM, on top of the "real" header */
|
356
|
-
nDiv.appendChild( nCTable );
|
357
|
-
document.body.appendChild( nDiv );
|
358
|
-
|
359
|
-
return {
|
360
|
-
"nNode": nCTable,
|
361
|
-
"nWrapper": nDiv,
|
362
|
-
"sType": sType,
|
363
|
-
"sPosition": "",
|
364
|
-
"sTop": "",
|
365
|
-
"sLeft": "",
|
366
|
-
"fnClone": fnClone,
|
367
|
-
"iCells": iCells
|
368
|
-
};
|
185
|
+
return this.c.footerOffset;
|
369
186
|
},
|
370
187
|
|
371
|
-
|
372
|
-
|
373
|
-
*
|
374
|
-
* Returns: -
|
375
|
-
* Inputs: -
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Recalculate the position of the fixed elements and force them into place
|
376
191
|
*/
|
377
|
-
|
192
|
+
update: function ()
|
378
193
|
{
|
379
|
-
|
380
|
-
|
381
|
-
m = s.oMes,
|
382
|
-
jqTable = $(s.nTable),
|
383
|
-
oOffset = jqTable.offset(),
|
384
|
-
iParentScrollTop = this._fnSumScroll( s.nTable.parentNode, 'scrollTop' ),
|
385
|
-
iParentScrollLeft = this._fnSumScroll( s.nTable.parentNode, 'scrollLeft' );
|
386
|
-
|
387
|
-
m.iTableWidth = jqTable.outerWidth();
|
388
|
-
m.iTableHeight = jqTable.outerHeight();
|
389
|
-
m.iTableLeft = oOffset.left + s.nTable.parentNode.scrollLeft;
|
390
|
-
m.iTableTop = oOffset.top + iParentScrollTop;
|
391
|
-
m.iTableRight = m.iTableLeft + m.iTableWidth;
|
392
|
-
m.iTableRight = FixedHeader.oDoc.iWidth - m.iTableLeft - m.iTableWidth;
|
393
|
-
m.iTableBottom = FixedHeader.oDoc.iHeight - m.iTableTop - m.iTableHeight;
|
194
|
+
this._positions();
|
195
|
+
this._scroll( true );
|
394
196
|
},
|
395
197
|
|
396
|
-
/*
|
397
|
-
* Function: _fnSumScroll
|
398
|
-
* Purpose: Sum node parameters all the way to the top
|
399
|
-
* Returns: int: sum
|
400
|
-
* Inputs: node:n - node to consider
|
401
|
-
* string:side - scrollTop or scrollLeft
|
402
|
-
*/
|
403
|
-
_fnSumScroll: function ( n, side )
|
404
|
-
{
|
405
|
-
var i = n[side];
|
406
|
-
while ( n = n.parentNode )
|
407
|
-
{
|
408
|
-
if ( n.nodeName == 'HTML' || n.nodeName == 'BODY' )
|
409
|
-
{
|
410
|
-
break;
|
411
|
-
}
|
412
|
-
i = n[side];
|
413
|
-
}
|
414
|
-
return i;
|
415
|
-
},
|
416
198
|
|
417
|
-
/*
|
418
|
-
*
|
419
|
-
* Purpose: Loop over the fixed elements for this table and update their positions
|
420
|
-
* Returns: -
|
421
|
-
* Inputs: -
|
199
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
200
|
+
* Constructor
|
422
201
|
*/
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
{
|
430
|
-
if ( s.aoCache[i].sType == "fixedHeader" )
|
431
|
-
{
|
432
|
-
this._fnScrollFixedHeader( s.aoCache[i] );
|
433
|
-
}
|
434
|
-
else if ( s.aoCache[i].sType == "fixedFooter" )
|
435
|
-
{
|
436
|
-
this._fnScrollFixedFooter( s.aoCache[i] );
|
437
|
-
}
|
438
|
-
else if ( s.aoCache[i].sType == "fixedLeft" )
|
439
|
-
{
|
440
|
-
this._fnScrollHorizontalLeft( s.aoCache[i] );
|
441
|
-
}
|
442
|
-
else
|
443
|
-
{
|
444
|
-
this._fnScrollHorizontalRight( s.aoCache[i] );
|
445
|
-
}
|
446
|
-
}
|
447
|
-
},
|
448
|
-
|
449
|
-
/*
|
450
|
-
* Function: _fnUpdateClones
|
451
|
-
* Purpose: Loop over the fixed elements for this table and call their cloning functions
|
452
|
-
* Returns: -
|
453
|
-
* Inputs: -
|
202
|
+
|
203
|
+
/**
|
204
|
+
* FixedHeader constructor - adding the required event listeners and
|
205
|
+
* simple initialisation
|
206
|
+
*
|
207
|
+
* @private
|
454
208
|
*/
|
455
|
-
|
209
|
+
_constructor: function ()
|
456
210
|
{
|
457
|
-
var
|
211
|
+
var that = this;
|
212
|
+
var dt = this.s.dt;
|
458
213
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
s.
|
464
|
-
|
214
|
+
$(window)
|
215
|
+
.on( 'scroll'+this.s.namespace, function () {
|
216
|
+
that._scroll();
|
217
|
+
} )
|
218
|
+
.on( 'resize'+this.s.namespace, function () {
|
219
|
+
that.s.position.windowHeight = $(window).height();
|
220
|
+
that.update();
|
221
|
+
} );
|
465
222
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
}
|
223
|
+
dt.on( 'column-reorder.dt.dtfc column-visibility.dt.dtfc draw.dt.dtfc', function () {
|
224
|
+
that.update();
|
225
|
+
} );
|
470
226
|
|
471
|
-
|
472
|
-
|
473
|
-
|
227
|
+
dt.on( 'destroy.dtfc', function () {
|
228
|
+
dt.off( '.dtfc' );
|
229
|
+
$(window).off( that.s.namespace );
|
230
|
+
} );
|
231
|
+
|
232
|
+
this._positions();
|
233
|
+
this._scroll();
|
474
234
|
},
|
475
235
|
|
476
236
|
|
477
|
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
478
|
-
*
|
237
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
238
|
+
* Private methods
|
479
239
|
*/
|
480
240
|
|
481
|
-
|
482
|
-
*
|
483
|
-
*
|
484
|
-
*
|
485
|
-
*
|
241
|
+
/**
|
242
|
+
* Clone a fixed item to act as a place holder for the original element
|
243
|
+
* which is moved into a clone of the table element, and moved around the
|
244
|
+
* document to give the fixed effect.
|
245
|
+
*
|
246
|
+
* @param {string} item 'header' or 'footer'
|
247
|
+
* @param {boolean} force Force the clone to happen, or allow automatic
|
248
|
+
* decision (reuse existing if available)
|
249
|
+
* @private
|
486
250
|
*/
|
487
|
-
|
251
|
+
_clone: function ( item, force )
|
488
252
|
{
|
489
|
-
var
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
{
|
506
|
-
/* Middle */
|
507
|
-
this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
|
508
|
-
this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );
|
509
|
-
this._fnUpdateCache( oCache, 'sLeft', (oWin.iWidth-iFixedWidth)+"px", 'left', nTable.style );
|
510
|
-
}
|
511
|
-
else
|
512
|
-
{
|
513
|
-
/* Fully left aligned */
|
514
|
-
this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
|
515
|
-
this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
|
516
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
517
|
-
}
|
518
|
-
},
|
253
|
+
var dt = this.s.dt;
|
254
|
+
var itemDom = this.dom[ item ];
|
255
|
+
var itemElement = item === 'header' ?
|
256
|
+
this.dom.thead :
|
257
|
+
this.dom.tfoot;
|
258
|
+
|
259
|
+
if ( ! force && itemDom.floating ) {
|
260
|
+
// existing floating element - reuse it
|
261
|
+
itemDom.floating.removeClass( 'fixedHeader-floating fixedHeader-locked' );
|
262
|
+
}
|
263
|
+
else {
|
264
|
+
if ( itemDom.floating ) {
|
265
|
+
itemDom.placeholder.remove();
|
266
|
+
itemDom.floating.children().detach();
|
267
|
+
itemDom.floating.remove();
|
268
|
+
}
|
519
269
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
* Inputs: object:oCache - the cached values for this fixed element
|
525
|
-
*/
|
526
|
-
_fnScrollHorizontalLeft: function ( oCache )
|
527
|
-
{
|
528
|
-
var
|
529
|
-
s = this.fnGetSettings(),
|
530
|
-
oMes = s.oMes,
|
531
|
-
oWin = FixedHeader.oWin,
|
532
|
-
oDoc = FixedHeader.oDoc,
|
533
|
-
nTable = oCache.nWrapper,
|
534
|
-
iCellWidth = $(nTable).outerWidth();
|
535
|
-
|
536
|
-
if ( oWin.iScrollLeft < oMes.iTableLeft )
|
537
|
-
{
|
538
|
-
/* Fully left align */
|
539
|
-
this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
|
540
|
-
this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
|
541
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
542
|
-
}
|
543
|
-
else if ( oWin.iScrollLeft < oMes.iTableLeft+oMes.iTableWidth-iCellWidth )
|
544
|
-
{
|
545
|
-
this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
|
546
|
-
this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );
|
547
|
-
this._fnUpdateCache( oCache, 'sLeft', "0px", 'left', nTable.style );
|
548
|
-
}
|
549
|
-
else
|
550
|
-
{
|
551
|
-
/* Fully right align */
|
552
|
-
this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
|
553
|
-
this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
|
554
|
-
this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft+oMes.iTableWidth-iCellWidth)+"px", 'left', nTable.style );
|
555
|
-
}
|
556
|
-
},
|
270
|
+
itemDom.floating = $( dt.table().node().cloneNode( false ) )
|
271
|
+
.removeAttr( 'id' )
|
272
|
+
.append( itemElement )
|
273
|
+
.appendTo( 'body' );
|
557
274
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
_fnScrollFixedFooter: function ( oCache )
|
565
|
-
{
|
566
|
-
var
|
567
|
-
s = this.fnGetSettings(),
|
568
|
-
oMes = s.oMes,
|
569
|
-
oWin = FixedHeader.oWin,
|
570
|
-
oDoc = FixedHeader.oDoc,
|
571
|
-
nTable = oCache.nWrapper,
|
572
|
-
iTheadHeight = $("thead", s.nTable).outerHeight(),
|
573
|
-
iCellHeight = $(nTable).outerHeight();
|
574
|
-
|
575
|
-
if ( oWin.iScrollBottom < oMes.iTableBottom )
|
576
|
-
{
|
577
|
-
/* Below */
|
578
|
-
this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
|
579
|
-
this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+oMes.iTableHeight-iCellHeight)+"px", 'top', nTable.style );
|
580
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
581
|
-
}
|
582
|
-
else if ( oWin.iScrollBottom < oMes.iTableBottom+oMes.iTableHeight-iCellHeight-iTheadHeight )
|
583
|
-
{
|
584
|
-
this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
|
585
|
-
this._fnUpdateCache( oCache, 'sTop', (oWin.iHeight-iCellHeight)+"px", 'top', nTable.style );
|
586
|
-
this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style );
|
587
|
-
}
|
588
|
-
else
|
589
|
-
{
|
590
|
-
/* Above */
|
591
|
-
this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
|
592
|
-
this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iCellHeight)+"px", 'top', nTable.style );
|
593
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
275
|
+
// Insert a fake thead/tfoot into the DataTable to stop it jumping around
|
276
|
+
itemDom.placeholder = itemElement.clone( false );
|
277
|
+
itemDom.host.append( itemDom.placeholder );
|
278
|
+
|
279
|
+
// Clone widths
|
280
|
+
this._matchWidths( itemDom.placeholder, itemDom.floating );
|
594
281
|
}
|
595
282
|
},
|
596
283
|
|
597
|
-
|
598
|
-
*
|
599
|
-
*
|
600
|
-
*
|
601
|
-
*
|
284
|
+
/**
|
285
|
+
* Copy widths from the cells in one element to another. This is required
|
286
|
+
* for the footer as the footer in the main table takes its sizes from the
|
287
|
+
* header columns. That isn't present in the footer so to have it still
|
288
|
+
* align correctly, the sizes need to be copied over. It is also required
|
289
|
+
* for the header when auto width is not enabled
|
290
|
+
*
|
291
|
+
* @param {jQuery} from Copy widths from
|
292
|
+
* @param {jQuery} to Copy widths to
|
293
|
+
* @private
|
602
294
|
*/
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
for (var i = 0; i < anTbodies.length; ++i) {
|
615
|
-
iTbodyHeight += anTbodies[i].offsetHeight;
|
616
|
-
}
|
295
|
+
_matchWidths: function ( from, to ) {
|
296
|
+
var type = function ( name ) {
|
297
|
+
var toWidths = $(name, from)
|
298
|
+
.map( function () {
|
299
|
+
return $(this).width();
|
300
|
+
} ).toArray();
|
301
|
+
|
302
|
+
$(name, to).each( function ( i ) {
|
303
|
+
$(this).width( toWidths[i] ).css("min-width", toWidths[i] );
|
304
|
+
} );
|
305
|
+
};
|
617
306
|
|
618
|
-
|
619
|
-
|
620
|
-
/* Above the table */
|
621
|
-
this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
|
622
|
-
this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
|
623
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
624
|
-
}
|
625
|
-
else if ( oWin.iScrollTop + s.oOffset.top > oMes.iTableTop+iTbodyHeight )
|
626
|
-
{
|
627
|
-
/* At the bottom of the table */
|
628
|
-
this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
|
629
|
-
this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iTbodyHeight)+"px", 'top', nTable.style );
|
630
|
-
this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
|
631
|
-
}
|
632
|
-
else
|
633
|
-
{
|
634
|
-
/* In the middle of the table */
|
635
|
-
this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
|
636
|
-
this._fnUpdateCache( oCache, 'sTop', s.oOffset.top+"px", 'top', nTable.style );
|
637
|
-
this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style );
|
638
|
-
}
|
307
|
+
type( 'th' );
|
308
|
+
type( 'td' );
|
639
309
|
},
|
640
310
|
|
641
|
-
|
642
|
-
*
|
643
|
-
*
|
644
|
-
*
|
645
|
-
*
|
646
|
-
*
|
647
|
-
*
|
648
|
-
*
|
649
|
-
* object:oObj - object to update
|
311
|
+
/**
|
312
|
+
* Remove assigned widths from the cells in an element. This is required
|
313
|
+
* when inserting the footer back into the main table so the size is defined
|
314
|
+
* by the header columns and also when auto width is disabled in the
|
315
|
+
* DataTable.
|
316
|
+
*
|
317
|
+
* @param {string} item The `header` or `footer`
|
318
|
+
* @private
|
650
319
|
*/
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
{
|
655
|
-
|
656
|
-
oCache[sCache] = sSet;
|
320
|
+
_unsize: function ( item ) {
|
321
|
+
var el = this.dom[ item ].floating;
|
322
|
+
|
323
|
+
if ( el && (item === 'footer' || (item === 'header' && ! this.s.autoWidth)) ) {
|
324
|
+
$('th, td', el).css( 'width', '' );
|
657
325
|
}
|
658
326
|
},
|
659
327
|
|
660
|
-
|
661
|
-
|
662
328
|
/**
|
663
|
-
*
|
664
|
-
*
|
665
|
-
*
|
666
|
-
*
|
667
|
-
*
|
329
|
+
* Reposition the floating elements to take account of horizontal page
|
330
|
+
* scroll
|
331
|
+
*
|
332
|
+
* @param {string} item The `header` or `footer`
|
333
|
+
* @param {int} scrollLeft Document scrollLeft
|
334
|
+
* @private
|
668
335
|
*/
|
669
|
-
|
336
|
+
_horizontal: function ( item, scrollLeft )
|
670
337
|
{
|
671
|
-
var
|
338
|
+
var itemDom = this.dom[ item ];
|
339
|
+
var position = this.s.position;
|
340
|
+
var lastScrollLeft = this.s.scrollLeft;
|
672
341
|
|
673
|
-
if (
|
674
|
-
|
675
|
-
{
|
676
|
-
dest.className = source.className;
|
677
|
-
}
|
342
|
+
if ( itemDom.floating && lastScrollLeft[ item ] !== scrollLeft ) {
|
343
|
+
itemDom.floating.css( 'left', position.left - scrollLeft );
|
678
344
|
|
679
|
-
|
680
|
-
|
681
|
-
} );
|
345
|
+
lastScrollLeft[ item ] = scrollLeft;
|
346
|
+
}
|
682
347
|
},
|
683
348
|
|
684
|
-
|
685
|
-
|
686
|
-
*
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
*
|
691
|
-
*
|
692
|
-
*
|
693
|
-
*
|
349
|
+
/**
|
350
|
+
* Change from one display mode to another. Each fixed item can be in one
|
351
|
+
* of:
|
352
|
+
*
|
353
|
+
* * `in-place` - In the main DataTable
|
354
|
+
* * `in` - Floating over the DataTable
|
355
|
+
* * `below` - (Header only) Fixed to the bottom of the table body
|
356
|
+
* * `above` - (Footer only) Fixed to the top of the table body
|
357
|
+
*
|
358
|
+
* @param {string} mode Mode that the item should be shown in
|
359
|
+
* @param {string} item 'header' or 'footer'
|
360
|
+
* @param {boolean} forceChange Force a redraw of the mode, even if already
|
361
|
+
* in that mode.
|
362
|
+
* @private
|
694
363
|
*/
|
695
|
-
|
364
|
+
_modeChange: function ( mode, item, forceChange )
|
696
365
|
{
|
697
|
-
var
|
698
|
-
var
|
366
|
+
var dt = this.s.dt;
|
367
|
+
var itemDom = this.dom[ item ];
|
368
|
+
var position = this.s.position;
|
369
|
+
|
370
|
+
if ( mode === 'in-place' ) {
|
371
|
+
// Insert the header back into the table's real header
|
372
|
+
if ( itemDom.placeholder ) {
|
373
|
+
itemDom.placeholder.remove();
|
374
|
+
itemDom.placeholder = null;
|
375
|
+
}
|
699
376
|
|
700
|
-
|
701
|
-
{
|
702
|
-
this._fnClassUpdate( $('thead', s.nTable)[0], $('thead', nTable)[0] );
|
703
|
-
return;
|
704
|
-
}
|
377
|
+
this._unsize( item );
|
705
378
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
379
|
+
itemDom.host.append( item === 'header' ?
|
380
|
+
this.dom.thead :
|
381
|
+
this.dom.tfoot
|
382
|
+
);
|
710
383
|
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
nTable.removeChild( nTable.childNodes[0] );
|
384
|
+
if ( itemDom.floating ) {
|
385
|
+
itemDom.floating.remove();
|
386
|
+
itemDom.floating = null;
|
387
|
+
}
|
716
388
|
}
|
389
|
+
else if ( mode === 'in' ) {
|
390
|
+
// Remove the header from the read header and insert into a fixed
|
391
|
+
// positioned floating table clone
|
392
|
+
this._clone( item, forceChange );
|
717
393
|
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
var a = [];
|
724
|
-
var b = [];
|
394
|
+
itemDom.floating
|
395
|
+
.addClass( 'fixedHeader-floating' )
|
396
|
+
.css( item === 'header' ? 'top' : 'bottom', this.c[item+'Offset'] )
|
397
|
+
.css( 'left', position.left+'px' )
|
398
|
+
.css( 'width', position.width+'px' );
|
725
399
|
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
$("thead>tr td", s.nTable).each( function (i) {
|
731
|
-
b.push( $(this).width() );
|
732
|
-
} );
|
733
|
-
|
734
|
-
$("thead>tr th", s.nTable).each( function (i) {
|
735
|
-
$("thead>tr th:eq("+i+")", nTable).width( a[i] );
|
736
|
-
$(this).width( a[i] );
|
737
|
-
} );
|
738
|
-
|
739
|
-
$("thead>tr td", s.nTable).each( function (i) {
|
740
|
-
$("thead>tr td:eq("+i+")", nTable).width( b[i] );
|
741
|
-
$(this).width( b[i] );
|
742
|
-
} );
|
743
|
-
|
744
|
-
// Stop DataTables 1.9 from putting a focus ring on the headers when
|
745
|
-
// clicked to sort
|
746
|
-
$('th.sorting, th.sorting_desc, th.sorting_asc', nTable).bind( 'click', function () {
|
747
|
-
this.blur();
|
748
|
-
} );
|
749
|
-
},
|
750
|
-
|
751
|
-
/*
|
752
|
-
* Function: _fnCloneTfoot
|
753
|
-
* Purpose: Clone the tfoot element
|
754
|
-
* Returns: -
|
755
|
-
* Inputs: object:oCache - the cached values for this fixed element
|
756
|
-
*/
|
757
|
-
_fnCloneTfoot: function ( oCache )
|
758
|
-
{
|
759
|
-
var s = this.fnGetSettings();
|
760
|
-
var nTable = oCache.nNode;
|
761
|
-
|
762
|
-
/* Set the wrapper width to match that of the cloned table */
|
763
|
-
oCache.nWrapper.style.width = $(s.nTable).outerWidth()+"px";
|
764
|
-
|
765
|
-
/* Remove any children the cloned table has */
|
766
|
-
while ( nTable.childNodes.length > 0 )
|
767
|
-
{
|
768
|
-
nTable.removeChild( nTable.childNodes[0] );
|
400
|
+
if ( item === 'footer' ) {
|
401
|
+
itemDom.floating.css( 'top', '' );
|
402
|
+
}
|
769
403
|
}
|
404
|
+
else if ( mode === 'below' ) { // only used for the header
|
405
|
+
// Fix the position of the floating header at base of the table body
|
406
|
+
this._clone( item, forceChange );
|
770
407
|
|
771
|
-
|
772
|
-
|
773
|
-
|
408
|
+
itemDom.floating
|
409
|
+
.addClass( 'fixedHeader-locked' )
|
410
|
+
.css( 'top', position.tfootTop - position.theadHeight )
|
411
|
+
.css( 'left', position.left+'px' )
|
412
|
+
.css( 'width', position.width+'px' );
|
413
|
+
}
|
414
|
+
else if ( mode === 'above' ) { // only used for the footer
|
415
|
+
// Fix the position of the floating footer at top of the table body
|
416
|
+
this._clone( item, forceChange );
|
774
417
|
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
418
|
+
itemDom.floating
|
419
|
+
.addClass( 'fixedHeader-locked' )
|
420
|
+
.css( 'top', position.tbodyTop )
|
421
|
+
.css( 'left', position.left+'px' )
|
422
|
+
.css( 'width', position.width+'px' );
|
423
|
+
}
|
779
424
|
|
780
|
-
|
781
|
-
|
782
|
-
|
425
|
+
this.s.scrollLeft.header = -1;
|
426
|
+
this.s.scrollLeft.footer = -1;
|
427
|
+
this.s[item+'Mode'] = mode;
|
783
428
|
},
|
784
429
|
|
785
|
-
|
786
|
-
*
|
787
|
-
*
|
788
|
-
*
|
789
|
-
*
|
430
|
+
/**
|
431
|
+
* Cache the positional information that is required for the mode
|
432
|
+
* calculations that FixedHeader performs.
|
433
|
+
*
|
434
|
+
* @private
|
790
435
|
*/
|
791
|
-
|
436
|
+
_positions: function ()
|
792
437
|
{
|
793
|
-
var
|
794
|
-
var
|
795
|
-
var
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
$('td:' + sSelector, this).remove();
|
823
|
-
} );
|
824
|
-
|
825
|
-
this.fnEqualiseHeights( 'thead', nBody.parentNode, nTable );
|
826
|
-
this.fnEqualiseHeights( 'tbody', nBody.parentNode, nTable );
|
827
|
-
this.fnEqualiseHeights( 'tfoot', nBody.parentNode, nTable );
|
828
|
-
|
829
|
-
var iWidth = 0;
|
830
|
-
for (var i = 0; i < oCache.iCells; i++) {
|
831
|
-
iWidth += $('thead tr th:eq(' + i + ')', s.nTable).outerWidth();
|
438
|
+
var dt = this.s.dt;
|
439
|
+
var table = dt.table();
|
440
|
+
var position = this.s.position;
|
441
|
+
var dom = this.dom;
|
442
|
+
var tableNode = $(table.node());
|
443
|
+
|
444
|
+
// Need to use the header and footer that are in the main table,
|
445
|
+
// regardless of if they are clones, since they hold the positions we
|
446
|
+
// want to measure from
|
447
|
+
var thead = tableNode.children('thead');
|
448
|
+
var tfoot = tableNode.children('tfoot');
|
449
|
+
var tbody = dom.tbody;
|
450
|
+
|
451
|
+
position.visible = tableNode.is(':visible');
|
452
|
+
position.width = tableNode.outerWidth();
|
453
|
+
position.left = tableNode.offset().left;
|
454
|
+
position.theadTop = thead.offset().top;
|
455
|
+
position.tbodyTop = tbody.offset().top;
|
456
|
+
position.theadHeight = position.tbodyTop - position.theadTop;
|
457
|
+
|
458
|
+
if ( tfoot.length ) {
|
459
|
+
position.tfootTop = tfoot.offset().top;
|
460
|
+
position.tfootBottom = position.tfootTop + tfoot.outerHeight();
|
461
|
+
position.tfootHeight = position.tfootBottom - position.tfootTop;
|
462
|
+
}
|
463
|
+
else {
|
464
|
+
position.tfootTop = position.tbodyTop + tbody.outerHeight();
|
465
|
+
position.tfootBottom = position.tfootTop;
|
466
|
+
position.tfootHeight = position.tfootTop;
|
832
467
|
}
|
833
|
-
nTable.style.width = iWidth+"px";
|
834
|
-
oCache.nWrapper.style.width = iWidth+"px";
|
835
468
|
},
|
836
469
|
|
837
|
-
|
838
|
-
|
839
|
-
*
|
840
|
-
*
|
841
|
-
*
|
470
|
+
|
471
|
+
/**
|
472
|
+
* Mode calculation - determine what mode the fixed items should be placed
|
473
|
+
* into.
|
474
|
+
*
|
475
|
+
* @param {boolean} forceChange Force a redraw of the mode, even if already
|
476
|
+
* in that mode.
|
477
|
+
* @private
|
842
478
|
*/
|
843
|
-
|
479
|
+
_scroll: function ( forceChange )
|
844
480
|
{
|
845
|
-
var
|
846
|
-
var
|
847
|
-
var
|
848
|
-
var
|
849
|
-
|
850
|
-
/* Remove any children the cloned table has */
|
851
|
-
while ( nTable.childNodes.length > 0 )
|
852
|
-
{
|
853
|
-
nTable.removeChild( nTable.childNodes[0] );
|
854
|
-
}
|
481
|
+
var windowTop = $(document).scrollTop();
|
482
|
+
var windowLeft = $(document).scrollLeft();
|
483
|
+
var position = this.s.position;
|
484
|
+
var headerMode, footerMode;
|
855
485
|
|
856
|
-
|
857
|
-
|
858
|
-
nTable.appendChild( $("tbody", s.nTable).clone(true)[0] );
|
859
|
-
if ( s.bFooter )
|
860
|
-
{
|
861
|
-
nTable.appendChild( $("tfoot", s.nTable).clone(true)[0] );
|
486
|
+
if ( ! this.s.enable ) {
|
487
|
+
return;
|
862
488
|
}
|
863
|
-
$('thead tr th:lt('+(iCols-oCache.iCells)+')', nTable).remove();
|
864
|
-
$('tfoot tr th:lt('+(iCols-oCache.iCells)+')', nTable).remove();
|
865
489
|
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
490
|
+
if ( this.c.header ) {
|
491
|
+
if ( ! position.visible || windowTop <= position.theadTop - this.c.headerOffset ) {
|
492
|
+
headerMode = 'in-place';
|
493
|
+
}
|
494
|
+
else if ( windowTop <= position.tfootTop - position.theadHeight - this.c.headerOffset ) {
|
495
|
+
headerMode = 'in';
|
496
|
+
}
|
497
|
+
else {
|
498
|
+
headerMode = 'below';
|
499
|
+
}
|
870
500
|
|
871
|
-
|
872
|
-
|
873
|
-
|
501
|
+
if ( forceChange || headerMode !== this.s.headerMode ) {
|
502
|
+
this._modeChange( headerMode, 'header', forceChange );
|
503
|
+
}
|
874
504
|
|
875
|
-
|
876
|
-
for (var i = 0; i < oCache.iCells; i++) {
|
877
|
-
iWidth += $('thead tr th:eq('+(iCols-1-i)+')', s.nTable).outerWidth();
|
505
|
+
this._horizontal( 'header', windowLeft );
|
878
506
|
}
|
879
|
-
nTable.style.width = iWidth+"px";
|
880
|
-
oCache.nWrapper.style.width = iWidth+"px";
|
881
|
-
},
|
882
507
|
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
* @private
|
893
|
-
*/
|
894
|
-
"fnEqualiseHeights": function ( parent, original, clone )
|
895
|
-
{
|
896
|
-
var that = this;
|
897
|
-
var originals = $(parent +' tr', original);
|
898
|
-
var height;
|
899
|
-
|
900
|
-
$(parent+' tr', clone).each( function (k) {
|
901
|
-
height = originals.eq( k ).css('height');
|
902
|
-
|
903
|
-
// This is nasty :-(. IE has a sub-pixel error even when setting
|
904
|
-
// the height below (the Firefox fix) which causes the fixed column
|
905
|
-
// to go out of alignment. Need to add a pixel before the assignment
|
906
|
-
// Can this be feature detected? Not sure how...
|
907
|
-
if ( navigator.appName == 'Microsoft Internet Explorer' ) {
|
908
|
-
height = parseInt( height, 10 ) + 1;
|
508
|
+
if ( this.c.footer && this.dom.tfoot.length ) {
|
509
|
+
if ( ! position.visible || windowTop + position.windowHeight >= position.tfootBottom + this.c.footerOffset ) {
|
510
|
+
footerMode = 'in-place';
|
511
|
+
}
|
512
|
+
else if ( position.windowHeight + windowTop > position.tbodyTop + position.tfootHeight + this.c.footerOffset ) {
|
513
|
+
footerMode = 'in';
|
514
|
+
}
|
515
|
+
else {
|
516
|
+
footerMode = 'above';
|
909
517
|
}
|
910
518
|
|
911
|
-
|
519
|
+
if ( forceChange || footerMode !== this.s.footerMode ) {
|
520
|
+
this._modeChange( footerMode, 'footer', forceChange );
|
521
|
+
}
|
912
522
|
|
913
|
-
|
914
|
-
|
915
|
-
// is a sub-pixel rounding error
|
916
|
-
originals.eq( k ).css( 'height', height );
|
917
|
-
} );
|
523
|
+
this._horizontal( 'footer', windowLeft );
|
524
|
+
}
|
918
525
|
}
|
919
|
-
};
|
526
|
+
} );
|
920
527
|
|
921
528
|
|
922
|
-
|
923
|
-
*
|
924
|
-
*
|
925
|
-
*
|
529
|
+
/**
|
530
|
+
* Version
|
531
|
+
* @type {String}
|
532
|
+
* @static
|
926
533
|
*/
|
534
|
+
FixedHeader.version = "3.1.0";
|
927
535
|
|
928
|
-
|
929
|
-
*
|
930
|
-
*
|
931
|
-
*
|
536
|
+
/**
|
537
|
+
* Defaults
|
538
|
+
* @type {Object}
|
539
|
+
* @static
|
932
540
|
*/
|
933
|
-
FixedHeader.
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
"iHeight": 0,
|
939
|
-
"iWidth": 0
|
541
|
+
FixedHeader.defaults = {
|
542
|
+
header: true,
|
543
|
+
footer: false,
|
544
|
+
headerOffset: 0,
|
545
|
+
footerOffset: 0
|
940
546
|
};
|
941
547
|
|
942
|
-
/*
|
943
|
-
* Variable: oDoc
|
944
|
-
* Purpose: Store information about the document size
|
945
|
-
* Scope: FixedHeader
|
946
|
-
*/
|
947
|
-
FixedHeader.oDoc = {
|
948
|
-
"iHeight": 0,
|
949
|
-
"iWidth": 0
|
950
|
-
};
|
951
548
|
|
952
|
-
/*
|
953
|
-
*
|
954
|
-
* Purpose: Array of functions that are to be used for the scrolling components
|
955
|
-
* Scope: FixedHeader
|
549
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
550
|
+
* DataTables interfaces
|
956
551
|
*/
|
957
|
-
FixedHeader.afnScroll = [];
|
958
552
|
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
* Returns: -
|
963
|
-
* Inputs: -
|
964
|
-
*/
|
965
|
-
FixedHeader.fnMeasure = function ()
|
966
|
-
{
|
967
|
-
var
|
968
|
-
jqWin = $(window),
|
969
|
-
jqDoc = $(document),
|
970
|
-
oWin = FixedHeader.oWin,
|
971
|
-
oDoc = FixedHeader.oDoc;
|
972
|
-
|
973
|
-
oDoc.iHeight = jqDoc.height();
|
974
|
-
oDoc.iWidth = jqDoc.width();
|
975
|
-
|
976
|
-
oWin.iHeight = jqWin.height();
|
977
|
-
oWin.iWidth = jqWin.width();
|
978
|
-
oWin.iScrollTop = jqWin.scrollTop();
|
979
|
-
oWin.iScrollLeft = jqWin.scrollLeft();
|
980
|
-
oWin.iScrollRight = oDoc.iWidth - oWin.iScrollLeft - oWin.iWidth;
|
981
|
-
oWin.iScrollBottom = oDoc.iHeight - oWin.iScrollTop - oWin.iHeight;
|
982
|
-
};
|
553
|
+
// Attach for constructor access
|
554
|
+
$.fn.dataTable.FixedHeader = FixedHeader;
|
555
|
+
$.fn.DataTable.FixedHeader = FixedHeader;
|
983
556
|
|
984
557
|
|
985
|
-
FixedHeader
|
558
|
+
// DataTables creation - check if the FixedHeader option has been defined on the
|
559
|
+
// table and if so, initialise
|
560
|
+
$(document).on( 'init.dt.dtb', function (e, settings, json) {
|
561
|
+
if ( e.namespace !== 'dt' ) {
|
562
|
+
return;
|
563
|
+
}
|
986
564
|
|
565
|
+
var opts = settings.oInit.fixedHeader || DataTable.defaults.fixedHeader;
|
987
566
|
|
988
|
-
|
989
|
-
|
990
|
-
|
567
|
+
if ( opts && ! settings._fixedHeader ) {
|
568
|
+
new FixedHeader( settings, opts );
|
569
|
+
}
|
570
|
+
} );
|
991
571
|
|
992
|
-
|
993
|
-
|
994
|
-
* done as an optimisation, to reduce calculation and proagation time
|
995
|
-
*/
|
996
|
-
$(window).scroll( function () {
|
997
|
-
FixedHeader.fnMeasure();
|
572
|
+
// DataTables API methods
|
573
|
+
DataTable.Api.register( 'fixedHeader()', function () {} );
|
998
574
|
|
999
|
-
|
1000
|
-
|
1001
|
-
|
575
|
+
DataTable.Api.register( 'fixedHeader.adjust()', function () {
|
576
|
+
return this.iterator( 'table', function ( ctx ) {
|
577
|
+
var fh = ctx._fixedHeader;
|
578
|
+
|
579
|
+
if ( fh ) {
|
580
|
+
fh.update();
|
581
|
+
}
|
582
|
+
} );
|
1002
583
|
} );
|
1003
584
|
|
585
|
+
DataTable.Api.register( 'fixedHeader.enable()', function ( flag ) {
|
586
|
+
return this.iterator( 'table', function ( ctx ) {
|
587
|
+
var fh = ctx._fixedHeader;
|
1004
588
|
|
1005
|
-
|
1006
|
-
|
589
|
+
if ( fh ) {
|
590
|
+
fh.enable( flag !== undefined ? flag : true );
|
591
|
+
}
|
592
|
+
} );
|
593
|
+
} );
|
1007
594
|
|
595
|
+
DataTable.Api.register( 'fixedHeader.disable()', function ( ) {
|
596
|
+
return this.iterator( 'table', function ( ctx ) {
|
597
|
+
var fh = ctx._fixedHeader;
|
1008
598
|
|
1009
|
-
|
1010
|
-
|
599
|
+
if ( fh ) {
|
600
|
+
fh.enable( false );
|
601
|
+
}
|
602
|
+
} );
|
603
|
+
} );
|
1011
604
|
|
605
|
+
$.each( ['header', 'footer'], function ( i, el ) {
|
606
|
+
DataTable.Api.register( 'fixedHeader.'+el+'Offset()', function ( offset ) {
|
607
|
+
var ctx = this.context;
|
1012
608
|
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
// Node/CommonJS
|
1019
|
-
factory( require('jquery'), require('datatables') );
|
1020
|
-
}
|
1021
|
-
else if ( jQuery && !jQuery.fn.dataTable.FixedHeader ) {
|
1022
|
-
// Otherwise simply initialise as normal, stopping multiple evaluation
|
1023
|
-
factory( jQuery, jQuery.fn.dataTable );
|
1024
|
-
}
|
609
|
+
if ( offset === undefined ) {
|
610
|
+
return ctx.length && ctx[0]._fixedHeader ?
|
611
|
+
ctx[0]._fixedHeader[el +'Offset']() :
|
612
|
+
undefined;
|
613
|
+
}
|
1025
614
|
|
615
|
+
return this.iterator( 'table', function ( ctx ) {
|
616
|
+
var fh = ctx._fixedHeader;
|
617
|
+
|
618
|
+
if ( fh ) {
|
619
|
+
fh[ el +'Offset' ]( offset );
|
620
|
+
}
|
621
|
+
} );
|
622
|
+
} );
|
623
|
+
} );
|
1026
624
|
|
1027
|
-
})(window, document);
|
1028
625
|
|
626
|
+
return FixedHeader;
|
627
|
+
}));
|