MediaWiki:StickyTableHeaders.js: Difference between revisions
From Ephinea PSO Wiki
No edit summary |
|||
| Line 129: | Line 129: | ||
if(tables.length > 0) $window.on("scroll", updateTablesThrottle); | if(tables.length > 0) $window.on("scroll", updateTablesThrottle); | ||
})(); | })(); | ||
Revision as of 03:09, 5 November 2017
/******************************************************
* 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)";
for(var i = 0; i < this.mainHeaderCells.length; i++){
this.mainHeaderCells[i].css("transform", y === 0 ? "unset" : "translateY(" + y + "px)");
}
}
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;
var transformStyle = y === 0 ? "unset" : "translateY(" + y + "px)";
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);
})();