MediaWiki:CustomItemTracker.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 248: | Line 248: | ||
searchBox.addEventListener( | |||
"input", | |||
function() { | |||
searchValue = | |||
this.value.toLowerCase(); | |||
render(searchValue); | |||
setTimeout(function() { | |||
const newSearch = | |||
container.querySelector(".trackerSearch"); | |||
if (newSearch) { | |||
newSearch.focus(); | |||
newSearch.setSelectionRange( | |||
newSearch.value.length, | |||
newSearch.value.length | |||
); | |||
} | } | ||
); | |||
}, 0); | |||
} | |||
); | |||
Revision as of 16:34, 30 July 2026
mw.hook('wikipage.content').add(function () {
const container =
document.getElementById("customItemTracker");
if (!container) return;
const allowedUsers = [
"Hefner"
];
const currentUser =
mw.config.get("wgUserName");
let trackerData = {
tiers: [],
completed: {}
};
let images = [];
let searchValue = "";
function loadData() {
$.getJSON(
mw.util.wikiScript("api"),
{
action: "query",
titles: "Module:CustomItemTracker/data.json",
prop: "revisions",
rvprop: "content",
format: "json",
formatversion: 2
}
).done(function(data) {
const page =
data.query.pages[0];
if (!page.revisions)
return;
try {
trackerData =
JSON.parse(
page.revisions[0].content
);
} catch(e) {
console.error(
"Invalid tracker JSON",
e
);
return;
}
loadImages();
});
}
function loadImages() {
const allItems = [];
trackerData.tiers.forEach(function(tier) {
tier.items.forEach(function(item) {
allItems.push(item);
});
});
const templates =
allItems
.map(function(item) {
return "{{plinkp|" +
item.name +
"}}";
})
.join("\n");
$.getJSON(
"/api.php",
{
action: "parse",
text: templates,
format: "json"
}
).done(function(data) {
if (!data.parse)
return;
const wrapper =
document.createElement("div");
wrapper.innerHTML =
data.parse.text["*"];
images =
Array.from(
wrapper.querySelectorAll("img")
);
render();
});
}
function render(searchTerm = "") {
container.innerHTML = "";
let total = 0;
trackerData.tiers.forEach(function(tier) {
total += tier.items.length;
});
let completed = 0;
Object.keys(
trackerData.completed
).forEach(function(key) {
if (
trackerData.completed[key]
) {
completed++;
}
});
const progress =
document.createElement("div");
progress.className =
"trackerProgress";
progress.innerHTML =
`
Completed:
<strong>${completed}/${total}</strong>
(${total ? Math.floor((completed / total) * 100) : 0}%)
`;
container.appendChild(progress);
const searchBox =
document.createElement("input");
searchBox.type =
"text";
searchBox.placeholder =
"Search items...";
searchBox.className =
"trackerSearch";
searchBox.value =
searchTerm;
container.appendChild(searchBox);
searchBox.addEventListener(
"input",
function() {
searchValue =
this.value.toLowerCase();
render(searchValue);
setTimeout(function() {
const newSearch =
container.querySelector(".trackerSearch");
if (newSearch) {
newSearch.focus();
newSearch.setSelectionRange(
newSearch.value.length,
newSearch.value.length
);
}
}, 0);
}
);
let globalIndex = 0;
trackerData.tiers.forEach(function(tier) {
const filteredItems =
tier.items.filter(function(item) {
if (!searchTerm)
return true;
return item.name
.toLowerCase()
.includes(searchTerm);
});
// Keep index alignment with completed data
tier.items.forEach(function(item) {
if (
filteredItems.includes(item)
) {
return;
}
});
if (filteredItems.length === 0)
return;
const heading =
document.createElement("div");
heading.className =
"trackerTierHeading";
heading.textContent =
tier.name;
container.appendChild(heading);
const grid =
document.createElement("div");
grid.className =
"trackerGrid";
container.appendChild(grid);
tier.items.forEach(function(item) {
const index =
globalIndex++;
if (
searchTerm &&
!item.name
.toLowerCase()
.includes(searchTerm)
) {
return;
}
const tile =
document.createElement("div");
tile.className =
"trackerTile";
if (
trackerData.completed[index]
) {
tile.classList.add(
"completed"
);
}
const imageBox =
document.createElement("div");
imageBox.className =
"itemImage";
if (
images[index]
) {
const img =
images[index]
.cloneNode(true);
img.style.maxWidth =
"50px";
img.style.maxHeight =
"50px";
img.style.width =
"auto";
img.style.height =
"auto";
img.style.objectFit =
"contain";
imageBox.appendChild(img);
}
tile.appendChild(imageBox);
const name =
document.createElement("div");
name.className =
"itemName";
name.textContent =
item.name;
tile.appendChild(name);
tile.onclick =
function() {
if (
!allowedUsers.includes(
currentUser
)
) {
return;
}
trackerData.completed[index] =
!trackerData.completed[index];
saveData();
};
grid.appendChild(tile);
});
});
}
function saveData() {
$.post(
mw.util.wikiScript("api"),
{
action: "edit",
title:
"Module:CustomItemTracker/data.json",
token:
mw.user.tokens.get(
"csrfToken"
),
format: "json",
text:
JSON.stringify(
trackerData,
null,
4
)
}
).done(function() {
render(searchValue);
console.log(
"Custom Item Tracker updated"
);
});
}
loadData();
});