Widget:GetPageImages
<script> var pageTitle = ""; // MediaWiki template variable var subpages = false; if ("" == "true"){
subpages=true;
};
console.log(`Get images from page '${pageTitle}' — include subpages: ${subpages}`);
var apiBase = "https://wb.manorhouses.tibwiki.io/w/api.php"; var images = [];
function buildApiUrl(params) {
let url = apiBase + "?origin=*";
Object.keys(params).forEach(function(key) {
url += "&" + key + "=" + encodeURIComponent(params[key]);
});
return url;
}
// Fetch image titles for one or more pages function fetchImagesForTitles(titles) {
const BATCH_LIMIT = 50;
const titleChunks = [];
for (let i = 0; i< titles.length; i += BATCH_LIMIT) {
titleChunks.push(titles.slice(i, i + BATCH_LIMIT));
}
const fetchPromises = titleChunks.map(chunk => {
const params = {
action: "query",
prop: "images",
titles: chunk.join("|"),
format: "json",
imlimit: 100
};
return fetch(buildApiUrl(params))
.then(res => res.json())
.then(data => {
if (data.query && data.query.pages) {
let pages = data.query.pages;
for (let pageId in pages) {
let page = pages[pageId];
console.log(page);
if (page.images && page.images.length > 0) {
page.images.forEach(img => {
if (!images.includes(img.title)) {
images.push(img.title);
console.log("found image"+img.title);
}
console.log(images.length);
});
}
}
}
});
});
return Promise.all(fetchPromises);
}
// Fetch actual image URLs from image titles function fetchImageUrls(imageTitles) {
const BATCH_LIMIT = 50;
const imageChunks = [];
console.log(imageTitles);
for (let i = 0; i< imageTitles.length; i += BATCH_LIMIT) {
imageChunks.push(imageTitles.slice(i, i + BATCH_LIMIT));
}
const fetches = imageChunks.map(chunk => {
const params = {
action: "query",
titles: chunk.join("|"),
prop: "imageinfo",
iiprop: "url",
format: "json"
};
return fetch(buildApiUrl(params))
.then(res => res.json())
.then(data => {
const result = [];
if (data.query && data.query.pages) {
for (let pageId in data.query.pages) {
const file = data.query.pages[pageId];
if (file.imageinfo && file.imageinfo.length > 0) {
result.push({
title: file.title,
url: file.imageinfo[0].url
});
}
}
}
return result;
});
});
return Promise.all(fetches).then(results => results.flat());
}
// Render Bootstrap image cards function renderImageCards(images) {
const container = document.getElementById("image-cards-container");
if (!container) {
console.error("Missing container with id 'image-cards-container'");
return;
}
images.forEach(img => {
const card = document.createElement("div");
card.className = "card";
card.style.width = "30%";
card.style.margin = "1%";
const filePageTitle = img.title.replace(/^File:/, "");
const filePageUrl = "/wiki/" + encodeURIComponent(img.title);
card.innerHTML = `
<a href="${filePageUrl}" target="_blank">
<img src="${img.url}" class="card-img-top" alt="${filePageTitle}">
</a>
${filePageTitle}
`;
container.appendChild(card); });
}
// Get subpages, then fetch images from all function getSubpagesAndImages() {
const params = {
action: "query",
list: "allpages",
apprefix: pageTitle + "/", // Only subpages
aplimit: "max",
format: "json"
};
return fetch(buildApiUrl(params))
.then(res => res.json())
.then(data => {
if (!data.query || !data.query.allpages) {
console.warn("No subpages found or invalid response structure.");
return fetchImagesForTitles([pageTitle]);
}
let subpagesList = data.query.allpages.map(p => p.title);
subpagesList.unshift(pageTitle); // Include main page
return fetchImagesForTitles(subpagesList);
});
}
// Only main page function getMainPageImagesOnly() {
return fetchImagesForTitles([pageTitle]);
}
// Main execution const imageFetch = subpages ? getSubpagesAndImages() : getMainPageImagesOnly();
imageFetch
.then(() => {
if (images.length === 0) {
console.log("No images found.");
return;
}
return fetchImageUrls(images);
})
.then(imageObjects => {
if (imageObjects) {
renderImageCards(imageObjects);
}
})
.catch(err => {
console.error("Error loading images:", err);
});
</script>