jquery-datatables-rails 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}));
|