MediaWiki:StickyTableHeaders.js: Difference between revisions
From Ephinea PSO Wiki
No edit summary |
m (Protected "MediaWiki:StickyTableHeaders.js": JS admin ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))) |
||
| (2 intermediate revisions 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); | |||
} | |||
} | } | ||
} | } | ||
| Line 129: | Line 148: | ||
if(tables.length > 0) $window.on("scroll", updateTablesThrottle); | if(tables.length > 0) $window.on("scroll", updateTablesThrottle); | ||
})(); | })(); | ||
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);
})();