Bugzilla – Attachment 171962 Details for
Bug 36291
Scrolling glitch on datatables with fixed header
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 36291: Update fixedHeader to v4.0.1
Bug-36291-Update-fixedHeader-to-v401.patch (text/plain), 25.50 KB, created by
Baptiste Wojtkowski (bwoj)
on 2024-09-26 08:38:46 UTC
(
hide
)
Description:
Bug 36291: Update fixedHeader to v4.0.1
Filename:
MIME Type:
Creator:
Baptiste Wojtkowski (bwoj)
Created:
2024-09-26 08:38:46 UTC
Size:
25.50 KB
patch
obsolete
>From 29769457a578367815c698404998685e74fabd5c Mon Sep 17 00:00:00 2001 >From: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com> >Date: Thu, 26 Sep 2024 10:31:44 +0200 >Subject: [PATCH] Bug 36291: Update fixedHeader to v4.0.1 > >On testing bug 36130, I found that scrolling had some glitch (at least on my computer, Firefox on ARM64 macOS). > >I used the following command to fill the DB with several batches: > >``` >PERL5LIB=$PERL5LIB:./lib perl fake_data.pl --how-many 100 --entity ill >for x in {1..21}; do echo "INSERT INTO illbatches (name, backend, library_id, status_code, patron_id) VALUES ('$x', 'FreeForm', 'CPL', 'NEW', 52);"; done | koha-mysql kohadev >``` > >In order to solve this bug, we decided to update fixedHeader to v4.0.1 > >TEST PLAN: > >1. Have a fresh KTD >2. Run: > $ ktd --shell > k$ bash <(curl -s https://raw.githubusercontent.com/ammopt/koha-ill-dev/master/start-ill-dev.sh) > k$ cd > k$ git clone https://github.com/ammopt/koha-ill-dev.git > k$ cd koha-ill-dev/ > k$ sudo apt install libdata-faker-perl libtext-lorem-perl > k$ PERL5LIB=$PERL5LIB:./lib perl fake_data.pl --how-many 200 --entity ill > k$ for x in {1..21}; do echo "INSERT INTO illbatches (name, backend, library_id, status_code, patron_id) VALUES ('$x', 'FreeForm', 'CPL', 'NEW', 52);"; done | koha-mysql kohadev >3. Go to /cgi-bin/koha/ill/ill-requests.pl?method=batch_list >4. Scroll down >=> FAIL: Koha is your enemy! >5. Apply patch and refresh cache from server >6. Go to /cgi-bin/koha/ill/ill-requests.pl?method=batch_list >Koha and you signed a peace treaty! >--- > .../lib/datatables/datatables.css | 23 +- > .../lib/datatables/datatables.js | 443 ++++++++++++------ > 2 files changed, 304 insertions(+), 162 deletions(-) > >diff --git a/koha-tmpl/intranet-tmpl/lib/datatables/datatables.css b/koha-tmpl/intranet-tmpl/lib/datatables/datatables.css >index b828164..f2ddac2 100644 >--- a/koha-tmpl/intranet-tmpl/lib/datatables/datatables.css >+++ b/koha-tmpl/intranet-tmpl/lib/datatables/datatables.css >@@ -1235,18 +1235,12 @@ html.dark div.dt-button-collection { > box-shadow: 3px 4px 10px 1px rgba(0, 0, 0, 0.8); > } > >- >-table.fixedHeader-floating { >- background-color: white; >-} >- >-table.fixedHeader-floating.no-footer { >- border-bottom-width: 0; >-} >- >+/* fixedHeader 4.0.1 */ >+table.fixedHeader-floating, > table.fixedHeader-locked { >- position: absolute !important; >- background-color: white; >+ position: relative !important; >+ background-color: var(--dt-html-background); >+ background-color: var(--dt-html-background); > } > > @media print { >@@ -1254,13 +1248,8 @@ table.fixedHeader-locked { > display: none; > } > } >-html.dark table.fixedHeader-floating { >- background-color: var(--dt-html-background); >-} >-html.dark table.fixedHeader-locked { >- background-color: var(--dt-html-background); >-} > >+/* End of fixedHeader 4.0.1 */ > > table.dataTable.dtr-inline.collapsed > tbody > tr > td.child, > table.dataTable.dtr-inline.collapsed > tbody > tr > th.child, >diff --git a/koha-tmpl/intranet-tmpl/lib/datatables/datatables.js b/koha-tmpl/intranet-tmpl/lib/datatables/datatables.js >index d5de7e7..5e26229 100644 >--- a/koha-tmpl/intranet-tmpl/lib/datatables/datatables.js >+++ b/koha-tmpl/intranet-tmpl/lib/datatables/datatables.js >@@ -105931,7 +105931,7 @@ return DataTable; > })); > > >-/*! FixedHeader 3.4.0 >+/*! FixedHeader 4.0.1 > * © SpryMedia Ltd - datatables.net/license > */ > >@@ -105976,7 +105976,7 @@ return DataTable; > // Browser > factory( jQuery, window, document ); > } >-}(function( $, window, document, undefined ) { >+}(function( $, window, document ) { > 'use strict'; > var DataTable = $.fn.dataTable; > >@@ -105986,10 +105986,9 @@ var DataTable = $.fn.dataTable; > * @summary FixedHeader > * @description Fix a table's header or footer, so it is always visible while > * scrolling >- * @version 3.4.0 >- * @author SpryMedia Ltd (www.sprymedia.co.uk) >- * @contact www.sprymedia.co.uk >- * @copyright SpryMedia Ltd. >+ * @version 4.0.1 >+ * @author SpryMedia Ltd >+ * @contact datatables.net > * > * This source file is free software, available under the following license: > * MIT license - http://datatables.net/license/mit >@@ -106004,6 +106003,10 @@ var DataTable = $.fn.dataTable; > var _instCounter = 0; > > var FixedHeader = function (dt, config) { >+ if (!DataTable.versionCheck('2')) { >+ throw 'Warning: FixedHeader requires DataTables 2 or newer'; >+ } >+ > // Sanity check - you just know it will happen > if (!(this instanceof FixedHeader)) { > throw "FixedHeader must be initialised with the 'new' keyword."; >@@ -106052,13 +106055,13 @@ var FixedHeader = function (dt, config) { > header: { > host: null, > floating: null, >- floatingParent: $('<div class="dtfh-floatingparent">'), >+ floatingParent: $('<div class="dtfh-floatingparent"><div></div></div>'), > placeholder: null > }, > footer: { > host: null, > floating: null, >- floatingParent: $('<div class="dtfh-floatingparent">'), >+ floatingParent: $('<div class="dtfh-floatingparent"><div></div></div>'), > placeholder: null > } > }; >@@ -106068,7 +106071,9 @@ var FixedHeader = function (dt, config) { > > var dtSettings = dt.settings()[0]; > if (dtSettings._fixedHeader) { >- throw 'FixedHeader already initialised on table ' + dtSettings.nTable.id; >+ throw ( >+ 'FixedHeader already initialised on table ' + dtSettings.nTable.id >+ ); > } > > dtSettings._fixedHeader = this; >@@ -106197,6 +106202,8 @@ $.extend(FixedHeader.prototype, { > > this._positions(); > this._scroll(force !== undefined ? force : true); >+ this._widths(this.dom.header); >+ this._widths(this.dom.footer); > }, > > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * >@@ -106281,14 +106288,16 @@ $.extend(FixedHeader.prototype, { > > if (!force && itemDom.floating) { > // existing floating element - reuse it >- itemDom.floating.removeClass('fixedHeader-floating fixedHeader-locked'); >+ itemDom.floating.removeClass( >+ 'fixedHeader-floating fixedHeader-locked' >+ ); > } > else { > if (itemDom.floating) { > if (itemDom.placeholder !== null) { > itemDom.placeholder.remove(); > } >- this._unsize(item); >+ > itemDom.floating.children().detach(); > itemDom.floating.remove(); > } >@@ -106300,35 +106309,41 @@ $.extend(FixedHeader.prototype, { > itemDom.floating = $(dt.table().node().cloneNode(false)) > .attr('aria-hidden', 'true') > .css({ >- 'table-layout': 'fixed', > top: 0, > left: 0 > }) >- .removeAttr('id') >- .append(itemElement); >+ .removeAttr('id'); > > itemDom.floatingParent > .css({ >- width: scrollBody.width(), >+ width: scrollBody[0].offsetWidth, > overflow: 'hidden', > height: 'fit-content', > position: 'fixed', >- left: scrollEnabled ? tableNode.offset().left + scrollBody.scrollLeft() : 0 >+ left: scrollEnabled >+ ? tableNode.offset().left + scrollBody.scrollLeft() >+ : 0 > }) > .css( > item === 'header' > ? { > top: this.c.headerOffset, > bottom: '' >- } >+ } > : { > top: '', > bottom: this.c.footerOffset >- } >+ } >+ ) >+ .addClass( >+ item === 'footer' >+ ? 'dtfh-floatingparent-foot' >+ : 'dtfh-floatingparent-head' > ) >- .addClass(item === 'footer' ? 'dtfh-floatingparentfoot' : 'dtfh-floatingparenthead') >- .append(itemDom.floating) >- .appendTo('body'); >+ .appendTo('body') >+ .children() >+ .eq(0) >+ .append(itemDom.floating); > > this._stickyPosition(itemDom.floating, '-'); > >@@ -106341,14 +106356,42 @@ $.extend(FixedHeader.prototype, { > scrollLeftUpdate(); > scrollBody.off('scroll.dtfh').on('scroll.dtfh', scrollLeftUpdate); > >+ // Need padding on the header's container to allow for a scrollbar, >+ // just like how DataTables handles it >+ itemDom.floatingParent.children().css({ >+ width: 'fit-content', >+ paddingRight: that.s.dt.settings()[0].oBrowser.barWidth >+ }); >+ >+ // Blocker to hide the table behind the scrollbar - this needs to use >+ // fixed positioning in the container since we don't have an outer wrapper >+ let blocker = $( >+ item === 'footer' >+ ? 'div.dtfc-bottom-blocker' >+ : 'div.dtfc-top-blocker', >+ dt.table().container() >+ ); >+ >+ if (blocker.length) { >+ blocker >+ .clone() >+ .appendTo(itemDom.floatingParent) >+ .css({ >+ position: 'fixed', >+ right: blocker.width() >+ }); >+ } >+ > // Insert a fake thead/tfoot into the DataTable to stop it jumping around > itemDom.placeholder = itemElement.clone(false); > itemDom.placeholder.find('*[id]').removeAttr('id'); > >+ // Move the thead / tfoot elements around - original into the floating >+ // element and clone into the original table > itemDom.host.prepend(itemDom.placeholder); >+ itemDom.floating.append(itemElement); > >- // Clone widths >- this._matchWidths(itemDom.placeholder, itemDom.floating); >+ this._widths(itemDom); > } > }, > >@@ -106367,17 +106410,16 @@ $.extend(FixedHeader.prototype, { > if ($(this).css('position') === 'sticky') { > var right = $(this).css('right'); > var left = $(this).css('left'); >+ var potential; >+ > if (right !== 'auto' && !rtl) { >- // New position either adds or dismisses the barWidth >- var potential = >- +right.replace(/px/g, '') + >- (sign === '-' ? -1 : 1) * that.s.dt.settings()[0].oBrowser.barWidth; >+ potential = +right.replace(/px/g, '') >+ > $(this).css('right', potential > 0 ? potential : 0); > } > else if (left !== 'auto' && rtl) { >- var potential = >- +left.replace(/px/g, '') + >- (sign === '-' ? -1 : 1) * that.s.dt.settings()[0].oBrowser.barWidth; >+ potential = +left.replace(/px/g, ''); >+ > $(this).css('left', potential > 0 ? potential : 0); > } > } >@@ -106385,69 +106427,6 @@ $.extend(FixedHeader.prototype, { > } > }, > >- /** >- * Copy widths from the cells in one element to another. This is required >- * for the footer as the footer in the main table takes its sizes from the >- * header columns. That isn't present in the footer so to have it still >- * align correctly, the sizes need to be copied over. It is also required >- * for the header when auto width is not enabled >- * >- * @param {jQuery} from Copy widths from >- * @param {jQuery} to Copy widths to >- * @private >- */ >- _matchWidths: function (from, to) { >- var get = function (name) { >- return $(name, from) >- .map(function () { >- return ( >- $(this) >- .css('width') >- .replace(/[^\d\.]/g, '') * 1 >- ); >- }) >- .toArray(); >- }; >- >- var set = function (name, toWidths) { >- $(name, to).each(function (i) { >- $(this).css({ >- width: toWidths[i], >- minWidth: toWidths[i] >- }); >- }); >- }; >- >- var thWidths = get('th'); >- var tdWidths = get('td'); >- >- set('th', thWidths); >- set('td', tdWidths); >- }, >- >- /** >- * Remove assigned widths from the cells in an element. This is required >- * when inserting the footer back into the main table so the size is defined >- * by the header columns and also when auto width is disabled in the >- * DataTable. >- * >- * @param {string} item The `header` or `footer` >- * @private >- */ >- _unsize: function (item) { >- var el = this.dom[item].floating; >- >- if (el && (item === 'footer' || (item === 'header' && !this.s.autoWidth))) { >- $('th, td', el).css({ >- width: '', >- minWidth: '' >- }); >- } >- else if (el && item === 'header') { >- $('th, td', el).css('min-width', ''); >- } >- }, >- > /** > * Reposition the floating elements to take account of horizontal page > * scroll >@@ -106458,13 +106437,14 @@ $.extend(FixedHeader.prototype, { > */ > _horizontal: function (item, scrollLeft) { > var itemDom = this.dom[item]; >- var position = this.s.position; > var lastScrollLeft = this.s.scrollLeft; > > if (itemDom.floating && lastScrollLeft[item] !== scrollLeft) { > // If scrolling is enabled we need to match the floating header to the body > if (this._scrollEnabled()) { >- var newScrollLeft = $($(this.s.dt.table().node()).parent()).scrollLeft(); >+ var newScrollLeft = $( >+ $(this.s.dt.table().node()).parent() >+ ).scrollLeft(); > itemDom.floating.scrollLeft(newScrollLeft); > itemDom.floatingParent.scrollLeft(newScrollLeft); > } >@@ -106489,7 +106469,6 @@ $.extend(FixedHeader.prototype, { > * @private > */ > _modeChange: function (mode, item, forceChange) { >- var dt = this.s.dt; > var itemDom = this.dom[item]; > var position = this.s.position; > >@@ -106504,15 +106483,11 @@ $.extend(FixedHeader.prototype, { > > // It isn't trivial to add a !important css attribute... > var importantWidth = function (w) { >- itemDom.floating.attr('style', function (i, s) { >- return (s || '') + 'width: ' + w + 'px !important;'; >- }); >+ itemDom.floating[0].style.setProperty('width', w + 'px', 'important'); > > // If not scrolling also have to update the floatingParent > if (!scrollEnabled) { >- itemDom.floatingParent.attr('style', function (i, s) { >- return (s || '') + 'width: ' + w + 'px !important;'; >- }); >+ itemDom.floatingParent[0].style.setProperty('width', w + 'px', 'important'); > } > }; > >@@ -106531,8 +106506,6 @@ $.extend(FixedHeader.prototype, { > itemDom.placeholder = null; > } > >- this._unsize(item); >- > if (item === 'header') { > itemDom.host.prepend(tablePart); > } >@@ -106547,13 +106520,16 @@ $.extend(FixedHeader.prototype, { > } > > if (itemDom.floatingParent) { >+ itemDom.floatingParent.find('div.dtfc-top-blocker').remove(); > itemDom.floatingParent.remove(); > } > >- $($(itemDom.host.parent()).parent()).scrollLeft(scrollBody.scrollLeft()); >+ $($(itemDom.host.parent()).parent()).scrollLeft( >+ scrollBody.scrollLeft() >+ ); > } > else if (mode === 'in') { >- // Remove the header from the read header and insert into a fixed >+ // Remove the header from the real table and insert into a fixed > // positioned floating table clone > this._clone(item, forceChange); > >@@ -106568,17 +106544,23 @@ $.extend(FixedHeader.prototype, { > : position.tfootTop; > > // Calculate the amount that the footer or header needs to be shuffled >- var shuffle = >- item === 'footer' >- ? // footer and top of body isn't on screen >- bodyTop > windowBottom >- ? // Yes - push the footer below >- position.tfootHeight >- : // No - bottom set to the gap between the top of the body and the bottom of the window >- bodyTop + position.tfootHeight - windowBottom >- : // Otherwise must be a header so get the difference from the bottom of the >- // desired floating header and the bottom of the table body >- windowTop + this.c.headerOffset + position.theadHeight - bodyBottom; >+ var shuffle; >+ >+ if (item === 'footer') { >+ shuffle = >+ bodyTop > windowBottom >+ ? position.tfootHeight // Yes - push the footer below >+ : bodyTop + position.tfootHeight - windowBottom; // No >+ } >+ else { >+ // Otherwise must be a header so get the difference from the bottom of the >+ // desired floating header and the bottom of the table body >+ shuffle = >+ windowTop + >+ this.c.headerOffset + >+ position.theadHeight - >+ bodyBottom; >+ } > > // Set the top or bottom based off of the offset and the shuffle value > var prop = item === 'header' ? 'top' : 'bottom'; >@@ -106589,10 +106571,8 @@ $.extend(FixedHeader.prototype, { > .css(prop, val) > .css({ > left: position.left, >- height: item === 'header' ? position.theadHeight : position.tfootHeight, >- 'z-index': 2 >- }) >- .append(itemDom.floating); >+ 'z-index': 3 >+ }); > > importantWidth(position.width); > >@@ -106667,20 +106647,23 @@ $.extend(FixedHeader.prototype, { > position.width = tableNode.outerWidth(); > position.left = tableNode.offset().left; > position.theadTop = thead.offset().top; >- position.tbodyTop = scrollEnabled ? scrollBody.offset().top : tbody.offset().top; >- position.tbodyHeight = scrollEnabled ? scrollBody.outerHeight() : tbody.outerHeight(); >+ position.tbodyTop = scrollEnabled >+ ? scrollBody.offset().top >+ : tbody.offset().top; >+ position.tbodyHeight = scrollEnabled >+ ? scrollBody.outerHeight() >+ : tbody.outerHeight(); > position.theadHeight = thead.outerHeight(); > position.theadBottom = position.theadTop + position.theadHeight; >+ position.tfootTop = position.tbodyTop + position.tbodyHeight; //tfoot.offset().top; > > if (tfoot.length) { >- position.tfootTop = position.tbodyTop + position.tbodyHeight; //tfoot.offset().top; > position.tfootBottom = position.tfootTop + tfoot.outerHeight(); > position.tfootHeight = tfoot.outerHeight(); > } > else { >- position.tfootTop = position.tbodyTop + tbody.outerHeight(); > position.tfootBottom = position.tfootTop; >- position.tfootHeight = position.tfootTop; >+ position.tfootHeight = 0; > } > }, > >@@ -106715,10 +106698,12 @@ $.extend(FixedHeader.prototype, { > // Body Details > var bodyTop = scrollEnabled ? scrollOffset.top : position.tbodyTop; > var bodyLeft = scrollEnabled ? scrollOffset.left : position.left; >- var bodyBottom = scrollEnabled ? scrollOffset.top + scrollHeight : position.tfootTop; >- var bodyWidth = scrollEnabled ? scrollBody.outerWidth() : position.tbodyWidth; >- >- var windowBottom = windowTop + windowHeight; >+ var bodyBottom = scrollEnabled >+ ? scrollOffset.top + scrollHeight >+ : position.tfootTop; >+ var bodyWidth = scrollEnabled >+ ? scrollBody.outerWidth() >+ : position.tbodyWidth; > > if (this.c.header) { > if (!this.s.enable) { >@@ -106728,24 +106713,27 @@ $.extend(FixedHeader.prototype, { > // the scroll of the window plus the headerOffset and the height of the header > else if ( > !position.visible || >- windowTop + this.c.headerOffset + position.theadHeight <= bodyTop >+ windowTop + this.c.headerOffset + position.theadHeight <= >+ bodyTop > ) { > headerMode = 'in-place'; > } > // The header should be floated if > else if ( > // The scrolling plus the header offset plus the height of the header is lower than the top of the body >- windowTop + this.c.headerOffset + position.theadHeight > bodyTop && >+ windowTop + this.c.headerOffset + position.theadHeight > >+ bodyTop && > // And the scrolling at the top plus the header offset is above the bottom of the body >- windowTop + this.c.headerOffset + position.theadHeight < bodyBottom >+ windowTop + this.c.headerOffset + position.theadHeight < >+ bodyBottom > ) { > headerMode = 'in'; >- var scrollBody = $($(this.s.dt.table().node()).parent()); > > // Further to the above, If the scrolling plus the header offset plus the header height is lower > // than the bottom of the table a shuffle is required so have to force the calculation > if ( >- windowTop + this.c.headerOffset + position.theadHeight > bodyBottom || >+ windowTop + this.c.headerOffset + position.theadHeight > >+ bodyBottom || > this.dom.header.floatingParent === undefined > ) { > forceChange = true; >@@ -106756,6 +106744,8 @@ $.extend(FixedHeader.prototype, { > top: this.c.headerOffset, > position: 'fixed' > }) >+ .children() >+ .eq(0) > .append(this.dom.header.floating); > } > } >@@ -106780,7 +106770,11 @@ $.extend(FixedHeader.prototype, { > height: 0 > }; > >- if (this.c.footer && this.dom.tfoot.length) { >+ if ( >+ this.c.footer && >+ this.dom.tfoot.length && >+ this.dom.tfoot.find('th, td').length >+ ) { > if (!this.s.enable) { > footerMode = 'in-place'; > } >@@ -106791,7 +106785,8 @@ $.extend(FixedHeader.prototype, { > footerMode = 'in-place'; > } > else if ( >- bodyBottom + position.tfootHeight + this.c.footerOffset > windowBottom && >+ bodyBottom + position.tfootHeight + this.c.footerOffset > >+ windowBottom && > bodyTop + this.c.footerOffset < windowBottom > ) { > footerMode = 'in'; >@@ -106852,12 +106847,17 @@ $.extend(FixedHeader.prototype, { > > // Need some rounding here as sometimes very small decimal places are encountered > // If the actual height is bigger or equal to the height we just applied then the footer is "Floating" >- if (Math.round(scrollBody.outerHeight()) >= Math.round(newHeight)) { >+ if ( >+ Math.round(scrollBody.outerHeight()) >= >+ Math.round(newHeight) >+ ) { > $(this.dom.tfoot.parent()).addClass('fixedHeader-floating'); > } > // Otherwise max-width has kicked in so it is not floating > else { >- $(this.dom.tfoot.parent()).removeClass('fixedHeader-floating'); >+ $(this.dom.tfoot.parent()).removeClass( >+ 'fixedHeader-floating' >+ ); > } > } > } >@@ -106875,16 +106875,27 @@ $.extend(FixedHeader.prototype, { > if (this.s.dt.settings()[0]._fixedColumns !== undefined) { > var adjustBlocker = function (side, end, el) { > if (el === undefined) { >- var blocker = $('div.dtfc-' + side + '-' + end + '-blocker'); >+ var blocker = $( >+ 'div.dtfc-' + side + '-' + end + '-blocker' >+ ); > >- el = blocker.length === 0 ? null : blocker.clone().css('z-index', 1); >+ el = >+ blocker.length === 0 >+ ? null >+ : blocker.clone().css('z-index', 1); > } > > if (el !== null) { > if (headerMode === 'in' || headerMode === 'below') { > el.appendTo('body').css({ >- top: end === 'top' ? header.offset.top : footer.offset.top, >- left: side === 'right' ? bodyLeft + bodyWidth - el.width() : bodyLeft >+ top: >+ end === 'top' >+ ? header.offset.top >+ : footer.offset.top, >+ left: >+ side === 'right' >+ ? bodyLeft + bodyWidth - el.width() >+ : bodyLeft > }); > } > else { >@@ -106901,7 +106912,11 @@ $.extend(FixedHeader.prototype, { > 'top', > this.dom.header.rightBlocker > ); >- this.dom.header.leftBlocker = adjustBlocker('left', 'top', this.dom.header.leftBlocker); >+ this.dom.header.leftBlocker = adjustBlocker( >+ 'left', >+ 'top', >+ this.dom.header.leftBlocker >+ ); > this.dom.footer.rightBlocker = adjustBlocker( > 'right', > 'bottom', >@@ -106925,6 +106940,46 @@ $.extend(FixedHeader.prototype, { > return true; > } > return false; >+ }, >+ >+ /** >+ * Realign columns by using the colgroup tag and >+ * checking column widths >+ */ >+ _widths: function (itemDom) { >+ if (! itemDom || ! itemDom.placeholder) { >+ return; >+ } >+ >+ // Match the table overall width >+ var tableNode = $(this.s.dt.table().node()); >+ var scrollBody = $(tableNode.parent()); >+ >+ itemDom.floatingParent.css('width', scrollBody[0].offsetWidth); >+ itemDom.floating.css('width', tableNode[0].offsetWidth); >+ >+ // Strip out the old colgroup >+ $('colgroup', itemDom.floating).remove(); >+ >+ // Copy the `colgroup` element to define the number of columns - needed >+ // for complex header cases where a column might not have a unique >+ // header >+ var cols = itemDom.placeholder >+ .parent() >+ .find('colgroup') >+ .clone() >+ .appendTo(itemDom.floating) >+ .find('col'); >+ >+ // However, the widths defined in the colgroup from the DataTable might >+ // not exactly reflect the actual widths of the columns (content can >+ // force it to stretch). So we need to copy the actual widths into the >+ // colgroup / col's used for the floating header. >+ var widths = this.s.dt.columns(':visible').widths(); >+ >+ for (var i=0 ; i<widths.length ; i++) { >+ cols.eq(i).css('width', widths[i]); >+ } > } > }); > >@@ -106933,7 +106988,7 @@ $.extend(FixedHeader.prototype, { > * @type {String} > * @static > */ >-FixedHeader.version = '3.4.0'; >+FixedHeader.version = '4.0.1'; > > /** > * Defaults >@@ -106947,6 +107002,104 @@ FixedHeader.defaults = { > footerOffset: 0 > }; > >+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * >+ * DataTables interfaces >+ */ >+ >+// Attach for constructor access >+$.fn.dataTable.FixedHeader = FixedHeader; >+$.fn.DataTable.FixedHeader = FixedHeader; >+ >+// DataTables creation - check if the FixedHeader option has been defined on the >+// table and if so, initialise >+$(document).on('init.dt.dtfh', function (e, settings, json) { >+ if (e.namespace !== 'dt') { >+ return; >+ } >+ >+ var init = settings.oInit.fixedHeader; >+ var defaults = DataTable.defaults.fixedHeader; >+ >+ if ((init || defaults) && !settings._fixedHeader) { >+ var opts = $.extend({}, defaults, init); >+ >+ if (init !== false) { >+ new FixedHeader(settings, opts); >+ } >+ } >+}); >+ >+// DataTables API methods >+DataTable.Api.register('fixedHeader()', function () { }); >+ >+DataTable.Api.register('fixedHeader.adjust()', function () { >+ return this.iterator('table', function (ctx) { >+ var fh = ctx._fixedHeader; >+ >+ if (fh) { >+ fh.update(); >+ } >+ }); >+}); >+ >+DataTable.Api.register('fixedHeader.enable()', function (flag) { >+ return this.iterator('table', function (ctx) { >+ var fh = ctx._fixedHeader; >+ >+ flag = flag !== undefined ? flag : true; >+ if (fh && flag !== fh.enabled()) { >+ fh.enable(flag); >+ } >+ }); >+}); >+ >+DataTable.Api.register('fixedHeader.enabled()', function () { >+ if (this.context.length) { >+ var fh = this.context[0]._fixedHeader; >+ >+ if (fh) { >+ return fh.enabled(); >+ } >+ } >+ >+ return false; >+}); >+ >+DataTable.Api.register('fixedHeader.disable()', function () { >+ return this.iterator('table', function (ctx) { >+ var fh = ctx._fixedHeader; >+ >+ if (fh && fh.enabled()) { >+ fh.enable(false); >+ } >+ }); >+}); >+ >+$.each(['header', 'footer'], function (i, el) { >+ DataTable.Api.register('fixedHeader.' + el + 'Offset()', function (offset) { >+ var ctx = this.context; >+ >+ if (offset === undefined) { >+ return ctx.length && ctx[0]._fixedHeader >+ ? ctx[0]._fixedHeader[el + 'Offset']() >+ : undefined; >+ } >+ >+ return this.iterator('table', function (ctx) { >+ var fh = ctx._fixedHeader; >+ >+ if (fh) { >+ fh[el + 'Offset'](offset); >+ } >+ }); >+ }); >+}); >+ >+ >+return DataTable; >+})); >+ >+ > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > * DataTables interfaces > */ >-- >2.43.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 36291
:
171962
|
172022