1/*! FixedColumns 4.3.0
2 * © SpryMedia Ltd - datatables.net/license
3 */
4
5(function( factory ){
6	if ( typeof define === 'function' && define.amd ) {
7		// AMD
8		define( ['jquery', 'datatables.net'], function ( $ ) {
9			return factory( $, window, document );
10		} );
11	}
12	else if ( typeof exports === 'object' ) {
13		// CommonJS
14		var jq = require('jquery');
15		var cjsRequires = function (root, $) {
16			if ( ! $.fn.dataTable ) {
17				require('datatables.net')(root, $);
18			}
19		};
20
21		if (typeof window === 'undefined') {
22			module.exports = function (root, $) {
23				if ( ! root ) {
24					// CommonJS environments without a window global must pass a
25					// root. This will give an error otherwise
26					root = window;
27				}
28
29				if ( ! $ ) {
30					$ = jq( root );
31				}
32
33				cjsRequires( root, $ );
34				return factory( $, root, root.document );
35			};
36		}
37		else {
38			cjsRequires( window, jq );
39			module.exports = factory( jq, window, window.document );
40		}
41	}
42	else {
43		// Browser
44		factory( jQuery, window, document );
45	}
46}(function( $, window, document, undefined ) {
47'use strict';
48var DataTable = $.fn.dataTable;
49
50
51(function () {
52    'use strict';
53
54    var $$1;
55    var dataTable;
56    function setJQuery(jq) {
57        $$1 = jq;
58        dataTable = $$1.fn.dataTable;
59    }
60    var FixedColumns = /** @class */ (function () {
61        function FixedColumns(settings, opts) {
62            var _this = this;
63            // Check that the required version of DataTables is included
64            if (!dataTable || !dataTable.versionCheck || !dataTable.versionCheck('1.10.0')) {
65                throw new Error('FixedColumns requires DataTables 1.10 or newer');
66            }
67            var table = new dataTable.Api(settings);
68            this.classes = $$1.extend(true, {}, FixedColumns.classes);
69            // Get options from user
70            this.c = $$1.extend(true, {}, FixedColumns.defaults, opts);
71            // Backwards compatibility for deprecated leftColumns
72            if ((!opts || opts.left === undefined) && this.c.leftColumns !== undefined) {
73                this.c.left = this.c.leftColumns;
74            }
75            // Backwards compatibility for deprecated rightColumns
76            if ((!opts || opts.right === undefined) && this.c.rightColumns !== undefined) {
77                this.c.right = this.c.rightColumns;
78            }
79            this.s = {
80                barWidth: 0,
81                dt: table,
82                rtl: $$1('body').css('direction') === 'rtl'
83            };
84            // Common CSS for all blockers
85            var blockerCSS = {
86                'bottom': '0px',
87                'display': 'block',
88                'position': 'absolute',
89                'width': this.s.barWidth + 1 + 'px'
90            };
91            this.dom = {
92                leftBottomBlocker: $$1('<div>')
93                    .css(blockerCSS)
94                    .css('left', 0)
95                    .addClass(this.classes.leftBottomBlocker),
96                leftTopBlocker: $$1('<div>')
97                    .css(blockerCSS)
98                    .css({
99                    left: 0,
100                    top: 0
101                })
102                    .addClass(this.classes.leftTopBlocker),
103                rightBottomBlocker: $$1('<div>')
104                    .css(blockerCSS)
105                    .css('right', 0)
106                    .addClass(this.classes.rightBottomBlocker),
107                rightTopBlocker: $$1('<div>')
108                    .css(blockerCSS)
109                    .css({
110                    right: 0,
111                    top: 0
112                })
113                    .addClass(this.classes.rightTopBlocker)
114            };
115            if (this.s.dt.settings()[0]._bInitComplete) {
116                // Fixed Columns Initialisation
117                this._addStyles();
118                this._setKeyTableListener();
119            }
120            else {
121                table.one('init.dt.dtfc', function () {
122                    // Fixed Columns Initialisation
123                    _this._addStyles();
124                    _this._setKeyTableListener();
125                });
126            }
127            table.on('column-sizing.dt.dtfc', function () { return _this._addStyles(); });
128            // Make class available through dt object
129            table.settings()[0]._fixedColumns = this;
130            table.on('destroy', function () { return _this._destroy(); });
131            return this;
132        }
133        FixedColumns.prototype.left = function (newVal) {
134            // If the value is to change
135            if (newVal !== undefined) {
136                if (newVal >= 0 && newVal <= this.s.dt.columns().count()) {
137                    // Set the new values and redraw the columns
138                    this.c.left = newVal;
139                    this._addStyles();
140                }
141                return this;
142            }
143            return this.c.left;
144        };
145        FixedColumns.prototype.right = function (newVal) {
146            // If the value is to change
147            if (newVal !== undefined) {
148                if (newVal >= 0 && newVal <= this.s.dt.columns().count()) {
149                    // Set the new values and redraw the columns
150                    this.c.right = newVal;
151                    this._addStyles();
152                }
153                return this;
154            }
155            return this.c.right;
156        };
157        /**
158         * Iterates over the columns, fixing the appropriate ones to the left and right
159         */
160        FixedColumns.prototype._addStyles = function () {
161            // Set the bar width if vertical scrolling is enabled
162            if (this.s.dt.settings()[0].oScroll.sY) {
163                var scroll_1 = $$1(this.s.dt.table().node()).closest('div.dataTables_scrollBody')[0];
164                var barWidth = this.s.dt.settings()[0].oBrowser.barWidth;
165                if (scroll_1.offsetWidth - scroll_1.clientWidth >= barWidth) {
166                    this.s.barWidth = barWidth;
167                }
168                else {
169                    this.s.barWidth = 0;
170                }
171                this.dom.rightTopBlocker.css('width', this.s.barWidth + 1);
172                this.dom.leftTopBlocker.css('width', this.s.barWidth + 1);
173                this.dom.rightBottomBlocker.css('width', this.s.barWidth + 1);
174                this.dom.leftBottomBlocker.css('width', this.s.barWidth + 1);
175            }
176            var parentDiv = null;
177            // Get the header and it's height
178            var header = this.s.dt.column(0).header();
179            var headerHeight = null;
180            if (header !== null) {
181                header = $$1(header);
182                headerHeight = header.outerHeight() + 1;
183                parentDiv = $$1(header.closest('div.dataTables_scroll')).css('position', 'relative');
184            }
185            // Get the footer and it's height
186            var footer = this.s.dt.column(0).footer();
187            var footerHeight = null;
188            if (footer !== null) {
189                footer = $$1(footer);
190                footerHeight = footer.outerHeight();
191                // Only attempt to retrieve the parentDiv if it has not been retrieved already
192                if (parentDiv === null) {
193                    parentDiv = $$1(footer.closest('div.dataTables_scroll')).css('position', 'relative');
194                }
195            }
196            // Get the number of columns in the table - this is used often so better to only make 1 api call
197            var numCols = this.s.dt.columns().data().toArray().length;
198            // Tracker for the number of pixels should be left to the left of the table
199            var distLeft = 0;
200            // Sometimes the headers have slightly different widths so need to track them individually
201            var headLeft = 0;
202            // Get all of the row elements in the table
203            var rows = $$1(this.s.dt.table().node()).children('tbody').children('tr');
204            var invisibles = 0;
205            // When working from right to left we need to know how many are invisible before a point,
206            // without including those that are invisible after
207            var prevInvisible = new Map();
208            // Iterate over all of the columns
209            for (var i = 0; i < numCols; i++) {
210                var column = this.s.dt.column(i);
211                // Set the map for the previous column
212                if (i > 0) {
213                    prevInvisible.set(i - 1, invisibles);
214                }
215                if (!column.visible()) {
216                    invisibles++;
217                    continue;
218                }
219                // Get the columns header and footer element
220                var colHeader = $$1(column.header());
221                var colFooter = $$1(column.footer());
222                // If i is less than the value of left then this column should be fixed left
223                if (i - invisibles < this.c.left) {
224                    $$1(this.s.dt.table().node()).addClass(this.classes.tableFixedLeft);
225                    parentDiv.addClass(this.classes.tableFixedLeft);
226                    // Add the width of the previous node - only if we are on atleast the second column
227                    if (i - invisibles > 0) {
228                        var prevIdx = i;
229                        // Simply using the number of hidden columns doesn't work here,
230                        // if the first is hidden then this would be thrown off
231                        while (prevIdx + 1 < numCols) {
232                            var prevCol = this.s.dt.column(prevIdx - 1, { page: 'current' });
233                            if (prevCol.visible()) {
234                                distLeft += $$1(prevCol.nodes()[0]).outerWidth();
235                                headLeft += prevCol.header() ?
236                                    $$1(prevCol.header()).outerWidth() :
237                                    prevCol.footer() ?
238                                        $$1(prevCol.header()).outerWidth() :
239                                        0;
240                                break;
241                            }
242                            prevIdx--;
243                        }
244                    }
245                    // Iterate over all of the rows, fixing the cell to the left
246                    for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
247                        var row = rows_1[_i];
248                        $$1($$1(row).children()[i - invisibles])
249                            .css(this._getCellCSS(false, distLeft, 'left'))
250                            .addClass(this.classes.fixedLeft);
251                    }
252                    // Add the css for the header and the footer
253                    colHeader
254                        .css(this._getCellCSS(true, headLeft, 'left'))
255                        .addClass(this.classes.fixedLeft);
256                    colFooter
257                        .css(this._getCellCSS(true, headLeft, 'left'))
258                        .addClass(this.classes.fixedLeft);
259                }
260                else {
261                    // Iteriate through all of the rows, making sure they aren't currently trying to fix left
262                    for (var _a = 0, rows_2 = rows; _a < rows_2.length; _a++) {
263                        var row = rows_2[_a];
264                        var cell = $$1($$1(row).children()[i - invisibles]);
265                        // If the cell is trying to fix to the left, remove the class and the css
266                        if (cell.hasClass(this.classes.fixedLeft)) {
267                            cell
268                                .css(this._clearCellCSS('left'))
269                                .removeClass(this.classes.fixedLeft);
270                        }
271                    }
272                    // Make sure the header for this column isn't fixed left
273                    if (colHeader.hasClass(this.classes.fixedLeft)) {
274                        colHeader
275                            .css(this._clearCellCSS('left'))
276                            .removeClass(this.classes.fixedLeft);
277                    }
278                    // Make sure the footer for this column isn't fixed left
279                    if (colFooter.hasClass(this.classes.fixedLeft)) {
280                        colFooter
281                            .css(this._clearCellCSS('left'))
282                            .removeClass(this.classes.fixedLeft);
283                    }
284                }
285            }
286            var distRight = 0;
287            var headRight = 0;
288            // Counter for the number of invisible columns so far
289            var rightInvisibles = 0;
290            for (var i = numCols - 1; i >= 0; i--) {
291                var column = this.s.dt.column(i);
292                // If a column is invisible just skip it
293                if (!column.visible()) {
294                    rightInvisibles++;
295                    continue;
296                }
297                // Get the columns header and footer element
298                var colHeader = $$1(column.header());
299                var colFooter = $$1(column.footer());
300                // Get the number of visible columns that came before this one
301                var prev = prevInvisible.get(i);
302                if (prev === undefined) {
303                    // If it wasn't set then it was the last column so just use the final value
304                    prev = invisibles;
305                }
306                if (i + rightInvisibles >= numCols - this.c.right) {
307                    $$1(this.s.dt.table().node()).addClass(this.classes.tableFixedRight);
308                    parentDiv.addClass(this.classes.tableFixedRight);
309                    // Add the widht of the previous node, only if we are on atleast the second column
310                    if (i + 1 + rightInvisibles < numCols) {
311                        var prevIdx = i;
312                        // Simply using the number of hidden columns doesn't work here,
313                        // if the first is hidden then this would be thrown off
314                        while (prevIdx + 1 < numCols) {
315                            var prevCol = this.s.dt.column(prevIdx + 1, { page: 'current' });
316                            if (prevCol.visible()) {
317                                distRight += $$1(prevCol.nodes()[0]).outerWidth();
318                                headRight += prevCol.header() ?
319                                    $$1(prevCol.header()).outerWidth() :
320                                    prevCol.footer() ?
321                                        $$1(prevCol.header()).outerWidth() :
322                                        0;
323                                break;
324                            }
325                            prevIdx++;
326                        }
327                    }
328                    // Iterate over all of the rows, fixing the cell to the right
329                    for (var _b = 0, rows_3 = rows; _b < rows_3.length; _b++) {
330                        var row = rows_3[_b];
331                        $$1($$1(row).children()[i - prev])
332                            .css(this._getCellCSS(false, distRight, 'right'))
333                            .addClass(this.classes.fixedRight);
334                    }
335                    // Add the css for the header and the footer
336                    colHeader
337                        .css(this._getCellCSS(true, headRight, 'right'))
338                        .addClass(this.classes.fixedRight);
339                    colFooter
340                        .css(this._getCellCSS(true, headRight, 'right'))
341                        .addClass(this.classes.fixedRight);
342                }
343                else {
344                    // Iteriate through all of the rows, making sure they aren't currently trying to fix right
345                    for (var _c = 0, rows_4 = rows; _c < rows_4.length; _c++) {
346                        var row = rows_4[_c];
347                        var cell = $$1($$1(row).children()[i - prev]);
348                        // If the cell is trying to fix to the right, remove the class and the css
349                        if (cell.hasClass(this.classes.fixedRight)) {
350                            cell
351                                .css(this._clearCellCSS('right'))
352                                .removeClass(this.classes.fixedRight);
353                        }
354                    }
355                    // Make sure the header for this column isn't fixed right
356                    if (colHeader.hasClass(this.classes.fixedRight)) {
357                        colHeader
358                            .css(this._clearCellCSS('right'))
359                            .removeClass(this.classes.fixedRight);
360                    }
361                    // Make sure the footer for this column isn't fixed right
362                    if (colFooter.hasClass(this.classes.fixedRight)) {
363                        colFooter
364                            .css(this._clearCellCSS('right'))
365                            .removeClass(this.classes.fixedRight);
366                    }
367                }
368            }
369            // If there is a header with the index class and reading rtl then add right top blocker
370            if (header) {
371                if (!this.s.rtl) {
372                    this.dom.rightTopBlocker.outerHeight(headerHeight);
373                    parentDiv.append(this.dom.rightTopBlocker);
374                }
375                else {
376                    this.dom.leftTopBlocker.outerHeight(headerHeight);
377                    parentDiv.append(this.dom.leftTopBlocker);
378                }
379            }
380            // If there is a footer with the index class and reading rtl then add right bottom blocker
381            if (footer) {
382                if (!this.s.rtl) {
383                    this.dom.rightBottomBlocker.outerHeight(footerHeight);
384                    parentDiv.append(this.dom.rightBottomBlocker);
385                }
386                else {
387                    this.dom.leftBottomBlocker.outerHeight(footerHeight);
388                    parentDiv.append(this.dom.leftBottomBlocker);
389                }
390            }
391        };
392        /**
393         * Clean up
394         */
395        FixedColumns.prototype._destroy = function () {
396            this.s.dt.off('.dtfc');
397            this.dom.leftBottomBlocker.remove();
398            this.dom.leftTopBlocker.remove();
399            this.dom.rightBottomBlocker.remove();
400            this.dom.rightTopBlocker.remove();
401        };
402        /**
403         * Gets the correct CSS for the cell, header or footer based on options provided
404         *
405         * @param header Whether this cell is a header or a footer
406         * @param dist The distance that the cell should be moved away from the edge
407         * @param lr Indicator of fixing to the left or the right
408         * @returns An object containing the correct css
409         */
410        FixedColumns.prototype._getCellCSS = function (header, dist, lr) {
411            if (lr === 'left') {
412                return this.s.rtl
413                    ? {
414                        position: 'sticky',
415                        right: dist + 'px'
416                    }
417                    : {
418                        left: dist + 'px',
419                        position: 'sticky'
420                    };
421            }
422            else {
423                return this.s.rtl
424                    ? {
425                        left: dist + (header ? this.s.barWidth : 0) + 'px',
426                        position: 'sticky'
427                    }
428                    : {
429                        position: 'sticky',
430                        right: dist + (header ? this.s.barWidth : 0) + 'px'
431                    };
432            }
433        };
434        /**
435         * Gets the css that is required to clear the fixing to a side
436         *
437         * @param lr Indicator of fixing to the left or the right
438         * @returns An object containing the correct css
439         */
440        FixedColumns.prototype._clearCellCSS = function (lr) {
441            if (lr === 'left') {
442                return !this.s.rtl ?
443                    {
444                        left: '',
445                        position: ''
446                    } :
447                    {
448                        position: '',
449                        right: ''
450                    };
451            }
452            else {
453                return !this.s.rtl ?
454                    {
455                        position: '',
456                        right: ''
457                    } :
458                    {
459                        left: '',
460                        position: ''
461                    };
462            }
463        };
464        FixedColumns.prototype._setKeyTableListener = function () {
465            var _this = this;
466            this.s.dt.on('key-focus.dt.dtfc', function (e, dt, cell) {
467                var cellPos = $$1(cell.node()).offset();
468                var scroll = $$1($$1(_this.s.dt.table().node()).closest('div.dataTables_scrollBody'));
469                // If there are fixed columns to the left
470                if (_this.c.left > 0) {
471                    // Get the rightmost left fixed column header, it's position and it's width
472                    var rightMost = $$1(_this.s.dt.column(_this.c.left - 1).header());
473                    var rightMostPos = rightMost.offset();
474                    var rightMostWidth = rightMost.outerWidth();
475                    // If the current highlighted cell is left of the rightmost cell on the screen
476                    if (cellPos.left < rightMostPos.left + rightMostWidth) {
477                        // Scroll it into view
478                        var currScroll = scroll.scrollLeft();
479                        scroll.scrollLeft(currScroll - (rightMostPos.left + rightMostWidth - cellPos.left));
480                    }
481                }
482                // If there are fixed columns to the right
483                if (_this.c.right > 0) {
484                    // Get the number of columns and the width of the cell as doing right side calc
485                    var numCols = _this.s.dt.columns().data().toArray().length;
486                    var cellWidth = $$1(cell.node()).outerWidth();
487                    // Get the leftmost right fixed column header and it's position
488                    var leftMost = $$1(_this.s.dt.column(numCols - _this.c.right).header());
489                    var leftMostPos = leftMost.offset();
490                    // If the current highlighted cell is right of the leftmost cell on the screen
491                    if (cellPos.left + cellWidth > leftMostPos.left) {
492                        // Scroll it into view
493                        var currScroll = scroll.scrollLeft();
494                        scroll.scrollLeft(currScroll - (leftMostPos.left - (cellPos.left + cellWidth)));
495                    }
496                }
497            });
498            // Whenever a draw occurs there is potential for the data to have changed and therefore also the column widths
499            // Therefore it is necessary to recalculate the values for the fixed columns
500            this.s.dt.on('draw.dt.dtfc', function () {
501                _this._addStyles();
502            });
503            this.s.dt.on('column-reorder.dt.dtfc', function () {
504                _this._addStyles();
505            });
506            this.s.dt.on('column-visibility.dt.dtfc', function (e, settings, column, state, recalc) {
507                if (recalc && !settings.bDestroying) {
508                    setTimeout(function () {
509                        _this._addStyles();
510                    }, 50);
511                }
512            });
513        };
514        FixedColumns.version = '4.3.0';
515        FixedColumns.classes = {
516            fixedLeft: 'dtfc-fixed-left',
517            fixedRight: 'dtfc-fixed-right',
518            leftBottomBlocker: 'dtfc-left-bottom-blocker',
519            leftTopBlocker: 'dtfc-left-top-blocker',
520            rightBottomBlocker: 'dtfc-right-bottom-blocker',
521            rightTopBlocker: 'dtfc-right-top-blocker',
522            tableFixedLeft: 'dtfc-has-left',
523            tableFixedRight: 'dtfc-has-right'
524        };
525        FixedColumns.defaults = {
526            i18n: {
527                button: 'FixedColumns'
528            },
529            left: 1,
530            right: 0
531        };
532        return FixedColumns;
533    }());
534
535    /*! FixedColumns 4.3.0
536     * © SpryMedia Ltd - datatables.net/license
537     */
538    setJQuery($);
539    $.fn.dataTable.FixedColumns = FixedColumns;
540    $.fn.DataTable.FixedColumns = FixedColumns;
541    var apiRegister = DataTable.Api.register;
542    apiRegister('fixedColumns()', function () {
543        return this;
544    });
545    apiRegister('fixedColumns().left()', function (newVal) {
546        var ctx = this.context[0];
547        if (newVal !== undefined) {
548            ctx._fixedColumns.left(newVal);
549            return this;
550        }
551        else {
552            return ctx._fixedColumns.left();
553        }
554    });
555    apiRegister('fixedColumns().right()', function (newVal) {
556        var ctx = this.context[0];
557        if (newVal !== undefined) {
558            ctx._fixedColumns.right(newVal);
559            return this;
560        }
561        else {
562            return ctx._fixedColumns.right();
563        }
564    });
565    DataTable.ext.buttons.fixedColumns = {
566        action: function (e, dt, node, config) {
567            if ($(node).attr('active')) {
568                $(node).removeAttr('active').removeClass('active');
569                dt.fixedColumns().left(0);
570                dt.fixedColumns().right(0);
571            }
572            else {
573                $(node).attr('active', 'true').addClass('active');
574                dt.fixedColumns().left(config.config.left);
575                dt.fixedColumns().right(config.config.right);
576            }
577        },
578        config: {
579            left: 1,
580            right: 0
581        },
582        init: function (dt, node, config) {
583            if (dt.settings()[0]._fixedColumns === undefined) {
584                _init(dt.settings(), config);
585            }
586            $(node).attr('active', 'true').addClass('active');
587            dt.button(node).text(config.text || dt.i18n('buttons.fixedColumns', dt.settings()[0]._fixedColumns.c.i18n.button));
588        },
589        text: null
590    };
591    function _init(settings, options) {
592        if (options === void 0) { options = null; }
593        var api = new DataTable.Api(settings);
594        var opts = options
595            ? options
596            : api.init().fixedColumns || DataTable.defaults.fixedColumns;
597        var fixedColumns = new FixedColumns(api, opts);
598        return fixedColumns;
599    }
600    // Attach a listener to the document which listens for DataTables initialisation
601    // events so we can automatically initialise
602    $(document).on('plugin-init.dt', function (e, settings) {
603        if (e.namespace !== 'dt') {
604            return;
605        }
606        if (settings.oInit.fixedColumns ||
607            DataTable.defaults.fixedColumns) {
608            if (!settings._fixedColumns) {
609                _init(settings, null);
610            }
611        }
612    });
613
614})();
615
616
617return DataTable;
618}));
619