MediaWiki:Datatables.js: Difference between revisions
From PC Gaming Shelter
No edit summary |
No edit summary |
||
| Line 22: | Line 22: | ||
} | } | ||
if (!document.querySelector("# | if (!document.querySelector("#datatable-styles")) { | ||
$("<style/>", { | $("<style/>", { | ||
id: " | id: "datatable-styles", | ||
text: ` | text: ` | ||
table.dataTable > tbody > tr > td { | table.dataTable > tbody > tr > td { | ||
| Line 42: | Line 42: | ||
.dt-loading::before { | .dt-loading::before { | ||
animation: | animation: dt-loading 0.8s linear infinite; | ||
border: 0.25rem solid #dee2e6; | border: 0.25rem solid #dee2e6; | ||
border-radius: 50%; | border-radius: 50%; | ||
| Line 54: | Line 54: | ||
} | } | ||
@keyframes | @keyframes dt-loading { | ||
to { | to { | ||
transform: rotate(360deg); | transform: rotate(360deg); | ||
| Line 76: | Line 76: | ||
} | } | ||
$(" | $("#games > table").addClass("dt-loading").attr("aria-busy", "true"); | ||
/* Load JavaScript. */ | /* Load JavaScript. */ | ||
Revision as of 09:00, 17 June 2026
var selectors = [
"#games > table"
];
var found = false;
for (var i = 0; i < selectors.length; i++) {
if (document.querySelector(selectors[i])) {
found = true;
break;
}
}
/* ------------- DataTables Loader and initialisation ---------------- */
if (found === true) {
/* Load CSS. */
const dtsource =
"https://cdn.datatables.net/v/dt/moment-2.29.4/dt-2.3.7/b-3.2.6/b-colvis-3.2.6/b-html5-3.2.6/b-print-3.2.6/cc-1.2.0/date-1.6.3/fh-4.0.5/r-3.0.8/sc-2.4.3/sb-1.8.4/sp-2.3.5/sl-3.1.3/sr-1.4.3/datatables.min.css";
if (!document.querySelector('link[href*="datatables.min.css"]')) {
$("<link/>", { rel: "stylesheet", href: dtsource }).appendTo("head");
}
if (!document.querySelector("#datatable-styles")) {
$("<style/>", {
id: "datatable-styles",
text: `
table.dataTable > tbody > tr > td {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.dt-loading {
display: block !important;
min-height: 4rem;
position: relative;
}
.dt-loading > * {
display: none !important;
}
.dt-loading::before {
animation: dt-loading 0.8s linear infinite;
border: 0.25rem solid #dee2e6;
border-radius: 50%;
border-top-color: #6c757d;
content: "";
height: 2rem;
left: calc(50% - 1rem);
position: absolute;
top: 1rem;
width: 2rem;
}
@keyframes dt-loading {
to {
transform: rotate(360deg);
}
}
.dtsp-searchPane {
border: 1px solid #bbb;
}
.dtsp-paneButton.clearButton {
font-size: 1.5rem;
line-height: 1;
}
.dtsp-paneButton.clearButton:not(:disabled) {
color: var(--bs-danger, #dc3545);
}
`,
}).appendTo("head");
}
$("#games > table").addClass("dt-loading").attr("aria-busy", "true");
/* Load JavaScript. */
$.when(
mw.loader.getScript(
"https://cdn.datatables.net/v/dt/moment-2.29.4/dt-2.3.7/b-3.2.6/b-colvis-3.2.6/b-html5-3.2.6/b-print-3.2.6/cc-1.2.0/date-1.6.3/fh-4.0.5/r-3.0.8/sc-2.4.3/sb-1.8.4/sp-2.3.5/sl-3.1.3/sr-1.4.3/datatables.min.js",
),
).then(
() => {
window.datatablesLoaded = true;
initDataTable();
},
(e) => mw.log.error(e.message),
);
}
/* ------------- DataTables configuration ---------------------------- */
function initDataTable() {
function getDataTableColumnCount(table) {
var headerRow =
table.tHead && table.tHead.rows.length
? table.tHead.rows[table.tHead.rows.length - 1]
: null;
if (headerRow) {
return headerRow.cells.length;
}
return table.rows.length ? table.rows[0].cells.length : 0;
}
function normaliseDataTableRows(table, expectedColumnCount) {
$("tbody tr", table).each(function () {
var row = this;
var cellCount = row.cells.length;
if (cellCount === 1 && row.cells[0].colSpan > 1) {
return;
}
while (cellCount < expectedColumnCount) {
row.appendChild(document.createElement("td"));
cellCount++;
}
});
}
function waitForTableToSettle(table, callback) {
var settleTimer;
var timeoutTimer;
var observer;
var settled = false;
function finish() {
if (settled) return;
settled = true;
clearTimeout(settleTimer);
clearTimeout(timeoutTimer);
if (observer) {
observer.disconnect();
}
callback();
}
function scheduleFinish() {
clearTimeout(settleTimer);
settleTimer = setTimeout(finish, 500);
}
if (window.MutationObserver) {
observer = new MutationObserver(scheduleFinish);
observer.observe(table.tBodies[0] || table, {
childList: true,
subtree: true,
});
}
timeoutTimer = setTimeout(finish, 30000);
scheduleFinish();
}
function getAcceptsValues(html) {
return (html || "")
.split(/<br\s*\/?>/i)
.map((value) => value.trim())
.filter(Boolean);
}
function getTableData(table, columnCount) {
return Array.from(table.tBodies[0] ? table.tBodies[0].rows : [])
.filter((row) => !(row.cells.length === 1 && row.cells[0].colSpan > 1))
.map((row) => {
var data = Array.from(row.cells, (cell) => cell.innerHTML.trim());
while (data.length < columnCount) {
data.push("");
}
return data.slice(0, columnCount);
});
}
function buildTableLayout(table, titles) {
var headerRow = document.createElement("tr");
var tableHead = document.createElement("thead");
titles.forEach((title) => {
var headerCell = document.createElement("th");
headerCell.textContent = title;
headerRow.appendChild(headerCell);
});
table.replaceChildren(tableHead, document.createElement("tbody"));
tableHead.appendChild(headerRow);
}
function suppressSearchPaneBorders(container) {
function removeBorderClass() {
container.querySelectorAll(".dtsp-bordered").forEach(function (element) {
element.classList.remove("dtsp-bordered");
});
}
removeBorderClass();
new MutationObserver(removeBorderClass).observe(container, {
attributes: true,
attributeFilter: ["class"],
childList: true,
subtree: true,
});
}
function openFellowshipLinksInNewTab(dataTable) {
dataTable
.column(0)
.nodes()
.toArray()
.forEach(function (cell) {
cell.querySelectorAll("a").forEach(function (link) {
link.target = "_blank";
});
});
}
$(".dataTable")
.each(function () {
var table = this;
waitForTableToSettle(table, function () {
if ($.fn.dataTable.isDataTable(table)) {
return;
}
normaliseDataTableRows(table, getDataTableColumnCount(table));
$(table).DataTable({
dom: "f",
retrieve: true,
order: [[0, "asc"]],
pageLength: 1000,
});
});
});
// ----- GAMES ------
$("#games > table").each(function () {
var table = this;
waitForTableToSettle(table, function () {
if ($.fn.dataTable.isDataTable(table)) {
return;
}
var titles = [
"Game", "Developer", "Publisher", "Genre", "Platform", "Mode", "Released"
];
var data = getTableData(table, titles.length);
buildTableLayout(table, titles);
var dataTable = new DataTable(table, {
columns: [
{
title: "Game",
render: function (data, type) {
if (type === "display") {
return (
'<span style="display: list-item; margin-left: 1.25rem;">' +
data +
"</span>"
);
}
return data;
},
searchPanes: {
show: false,
},
},
{
title: "Developer",
visible: false,
searchPanes: {
show: true,
},
},
{
title: "Publisher",
visible: false,
searchPanes: {
show: true,
},
},
{
title: "Genre",
visible: false,
searchPanes: {
show: true,
},
},
{
title: "Platform",
visible: false,
searchPanes: {
show: true,
},
},
{
title: "Mode",
visible: false,
render: {
display: function (data) {
return data;
},
sp: function (data) {
return getAcceptsValues(data);
},
},
searchPanes: {
show: true,
orthogonal: "sp",
},
},
{
title: "Released",
visible: false,
searchPanes: {
show: true,
},
},
],
layout: {
topStart: null,
topEnd: null,
top2: {
searchPanes: {
cascadePanes: true,
initCollapsed: true,
layout: "columns-4",
columns: [1, 2, 3, 4, 5, 6],
},
},
top1: {
search: {
className: "mx-0 w-100",
},
},
},
order: [[0, "asc"]],
paging: false,
searchDelay: 400,
});
var lastGlobalSearch = dataTable.search();
var paneIndexes = [1, 2, 3, 4, 5, 6];
dataTable.on("draw.dt", function () {
var globalSearch = dataTable.search();
openFellowshipLinksInNewTab(dataTable);
if (globalSearch === lastGlobalSearch) {
return;
}
lastGlobalSearch = globalSearch;
paneIndexes.forEach(function (paneIndex) {
dataTable.searchPanes.rebuildPane(paneIndex, true);
});
});
dataTable.rows.add(data).draw();
$(".dataTable")
.removeClass("dt-loading")
.removeAttr("aria-busy")
.show();
dataTable.searchPanes.rebuildPane();
suppressSearchPaneBorders(document.querySelector(".dataTable"));
dataTable.columns.adjust().draw(false);
});
});
}
