MediaWiki:StickyTableHeaders.js: Difference between revisions
From Ephinea PSO Wiki
m (Protected "MediaWiki:StickyTableHeaders.js": JS admin ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))) |
|||
(One intermediate revision by one other user not shown) | |||
Line 78: | Line 78: | ||
var transformStyle = y === 0 ? "unset" : "translateY(" + y + "px)"; | var transformStyle = y === 0 ? "unset" : "translateY(" + y + "px)"; | ||
for(var i = 0; i < this.mainHeaderCells.length; i++){ | if(y > 0){ | ||
var transformStyle = "translateY(" + y + "px)"; | |||
if(!this.mainHeader.hasClass("floating")) this.mainHeader.addClass("floating"); | |||
for(var i = 0; i < this.mainHeaderCells.length; i++){ | |||
this.mainHeaderCells[i].css("transform", transformStyle); | |||
} | |||
}else{ | |||
var transformStyle = "unset"; | |||
if(this.mainHeader.hasClass("floating")) this.mainHeader.removeClass("floating"); | |||
for(var i = 0; i < this.mainHeaderCells.length; i++){ | |||
this.mainHeaderCells[i].css("transform", transformStyle); | |||
} | |||
} | } | ||
} | } | ||
Line 92: | Line 102: | ||
var delta = scrollTop - subTop + mainHeight; | var delta = scrollTop - subTop + mainHeight; | ||
var y = (delta < 0 || delta > tableBottom) ? 0 : delta - borderWidth; | var y = (delta < 0 || delta > tableBottom) ? 0 : delta - borderWidth; | ||
for(var j = 0; j < this.subHeaderCells[i].length; j++){ | if(y > 0){ | ||
this.subHeaderCells[i][j].css("transform", transformStyle); | var transformStyle = "translateY(" + y + "px)"; | ||
if(!subHeader.hasClass("floating")) subHeader.addClass("floating"); | |||
for(var j = 0; j < this.subHeaderCells[i].length; j++){ | |||
this.subHeaderCells[i][j].css("transform", transformStyle); | |||
} | |||
}else{ | |||
var transformStyle = "unset"; | |||
if(subHeader.hasClass("floating")) subHeader.removeClass("floating"); | |||
for(var j = 0; j < this.subHeaderCells[i].length; j++){ | |||
this.subHeaderCells[i][j].css("transform", transformStyle); | |||
} | |||
} | } | ||
} | } |
Latest revision as of 14:49, 7 July 2023
/****************************************************** * Usage: * * - Add the `sticky` class to the table element. * * - Add the `sticky-main` class to a header row * * to define it as the main header. * * - Optionally, add the `sticky-sub` class to any * * header rows to define them as sub-headers. * * * * Example: * * {| class="wikitable sticky" * * |- class="sticky-main" * * ! Name * * ! Color * * ! Score * * * * |- class="sticky-sub" * * ! colspan=3 | Fruits * * |- * * | Banana || Yellow || 10 * * |- * * | Pear || Green || 5 * * |- * * | Apple || Red || 7 * * * * |- class="sticky-sub" * * ! colspan=3 | Vegetables * * |- * * | Carrot || Orange || 8 * * |- * * | Potato || Brown || 6 * * |- * * | Eggplant || Purple || 10 * * * * |- class="sticky-sub" * * ! colspan=3 | Candy * * |- * * | Skittles || Rainbow || 4 * * |- * * | Chocolate || Brown || 7 * * |- * * | Liquorice || Black || 8 * * |} * * * *****************************************************/ (function(){ var $window = $(window); var borderWidth = 2; /**/ function StickyTable(tableElement){ this.tableElement = tableElement; this.mainHeader = $(".sticky-main", this.tableElement).first(); if(this.mainHeader.length === 0){ throw new TypeError("Invalid sticky table: Must contain a row with class `sticky-main`."); } this.mainHeaderCells = this.mainHeader.children().map(function(){ return $(this); }); this.subHeaders = $(".sticky-sub", this.tableElement).map(function(){ return $(this); }); this.subHeaderCells = []; for(var i = 0; i < this.subHeaders.length; i++){ this.subHeaderCells[i] = this.subHeaders[i].children().map(function(){ return $(this); }); } } StickyTable.prototype.updateMain = function updateMain(scrollTop){ var tableHeight = this.tableElement.height(); var delta = scrollTop - this.mainHeader.offset().top; var y = (delta < 0 || delta > tableHeight) ? 0 : delta - borderWidth; var transformStyle = y === 0 ? "unset" : "translateY(" + y + "px)"; if(y > 0){ var transformStyle = "translateY(" + y + "px)"; if(!this.mainHeader.hasClass("floating")) this.mainHeader.addClass("floating"); for(var i = 0; i < this.mainHeaderCells.length; i++){ this.mainHeaderCells[i].css("transform", transformStyle); } }else{ var transformStyle = "unset"; if(this.mainHeader.hasClass("floating")) this.mainHeader.removeClass("floating"); for(var i = 0; i < this.mainHeaderCells.length; i++){ this.mainHeaderCells[i].css("transform", transformStyle); } } } StickyTable.prototype.updateSubs = function updateSub(scrollTop){ var mainHeight = this.mainHeader.height() - borderWidth; var tableTop = this.tableElement.offset().top; for(var i = 0; i < this.subHeaders.length; i++){ var subHeader = this.subHeaders[i]; var subTop = subHeader.offset().top; var tableBottom = this.tableElement.height() - subTop + tableTop; var delta = scrollTop - subTop + mainHeight; var y = (delta < 0 || delta > tableBottom) ? 0 : delta - borderWidth; if(y > 0){ var transformStyle = "translateY(" + y + "px)"; if(!subHeader.hasClass("floating")) subHeader.addClass("floating"); for(var j = 0; j < this.subHeaderCells[i].length; j++){ this.subHeaderCells[i][j].css("transform", transformStyle); } }else{ var transformStyle = "unset"; if(subHeader.hasClass("floating")) subHeader.removeClass("floating"); for(var j = 0; j < this.subHeaderCells[i].length; j++){ this.subHeaderCells[i][j].css("transform", transformStyle); } } } } StickyTable.prototype.update = function update(scrollTop){ this.updateMain(scrollTop); this.updateSubs(scrollTop); } /**/ var tables = $("table.sticky").map(function(){ return new StickyTable($(this)); }); var updating = false; function updateTables(){ var scrollTop = $window.scrollTop() for(var i = 0; i < tables.length; i++){ var table = tables[i]; if(table.tableElement.is(":visible")) table.update(scrollTop); } updating = false; } function updateTablesThrottle(){ if(!updating){ window.requestAnimationFrame(updateTables); updating = true; } } if(tables.length > 0) $window.on("scroll", updateTablesThrottle); })();