MediaWiki:CustomItemTracker.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 22: | Line 22: | ||
let images = | let images = {}; | ||
let searchValue = ""; | let searchValue = ""; | ||
| Line 119: | Line 120: | ||
$. | $.post( | ||
"/api.php", | "/api.php", | ||
{ | { | ||
| Line 131: | Line 132: | ||
if (!data.parse) | if (!data.parse) { | ||
console.warn( | |||
"Image parse failed", | |||
data | |||
); | |||
images = {}; | |||
render(); | |||
return; | return; | ||
} | |||
| Line 146: | Line 159: | ||
const parsedImages = | |||
Array.from( | Array.from( | ||
wrapper.querySelectorAll("img") | wrapper.querySelectorAll("img") | ||
); | ); | ||
images = {}; | |||
allItems.forEach(function(item, index) { | |||
if (parsedImages[index]) { | |||
images[item.name] = | |||
parsedImages[index]; | |||
} | |||
}); | |||
| Line 254: | Line 286: | ||
searchValue = | searchValue = | ||
this.value.toLowerCase(); | 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) { | trackerData.tiers.forEach(function(tier) { | ||
| Line 282: | Line 332: | ||
}); | }); | ||
| Line 339: | Line 373: | ||
const index = | |||
trackerData.tiers | |||
.flatMap(t => t.items) | |||
.indexOf(item); | |||
| Line 392: | Line 428: | ||
if ( | if ( | ||
images[ | images[item.name] | ||
) { | ) { | ||
const img = | const img = | ||
images[ | images[item.name] | ||
.cloneNode(true); | .cloneNode(true); | ||
Latest revision as of 17:12, 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");
$.post(
"/api.php",
{
action: "parse",
text: templates,
format: "json"
}
).done(function(data) {
if (!data.parse) {
console.warn(
"Image parse failed",
data
);
images = {};
render();
return;
}
const wrapper =
document.createElement("div");
wrapper.innerHTML =
data.parse.text["*"];
const parsedImages =
Array.from(
wrapper.querySelectorAll("img")
);
images = {};
allItems.forEach(function(item, index) {
if (parsedImages[index]) {
images[item.name] =
parsedImages[index];
}
});
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);
});
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 =
trackerData.tiers
.flatMap(t => t.items)
.indexOf(item);
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[item.name]
) {
const img =
images[item.name]
.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();
});