MediaWiki:Common.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
$(document).ready(function () {
// Global variables
var cards = $(".card");
var showArticleWrapper = $("#show-article-wrapper");
var areFiltersActive = false;
// Make header-box in Home clickable
$(".head-box").click(function () {
window.location.href = "/Main_Page"; // Redirects to the home page
});
// Loop through each card to format related articles
cards.each(function () {
// Check if the card has related articles
var relatedArticles = $(this).find(".related-articles");
if (relatedArticles.length > 0) {
// Get all the related article elements
var relatedArticleElements = relatedArticles.find(".related-article");
// Create an array to store unique related articles
var uniqueArticles = [];
// Loop through each related article element
relatedArticleElements.each(function () {
// Remove <p> tags from the article
$(this).find("p").remove();
// Convert the article HTML to a string
var articleHTML = $(this)[0].outerHTML;
// Check if the article HTML already exists in the uniqueArticles array
if ($.inArray(articleHTML, uniqueArticles) === -1) {
// If it doesn't exist, add it to the uniqueArticles array
uniqueArticles.push(articleHTML);
}
});
// Clear the content of the related articles container
relatedArticles.empty();
// Append the unique related articles back to the container
relatedArticles.append(uniqueArticles.join(""));
}
});
// Utility Functions
function sortChronologically() {
var cards = $(".list-container .card").get();
cards.sort(function (a, b) {
var numberA = parseInt(
$(a).find(".entry-number").text().replace(/\[|\]/g, ""),
10
);
var numberB = parseInt(
$(b).find(".entry-number").text().replace(/\[|\]/g, ""),
10
);
return numberB - numberA; // Descending order
});
$.each(cards, function (index, item) {
$(".list-container").append(item);
});
}
function randomizeCards(selector) {
var cards = $(selector).get();
var i = cards.length,
j,
temp;
while (--i > 0) {
j = Math.floor(Math.random() * (i + 1));
temp = cards[i];
cards[i] = cards[j];
cards[j] = temp;
}
$.each(cards, function (index, item) {
$(selector).parent().append(item);
});
}
function sortAlphabetically(selector) {
var cards = $(selector).get();
cards.sort(function (a, b) {
var titleA = $(a).find(".title").text().toUpperCase();
var titleB = $(b).find(".title").text().toUpperCase();
return titleA < titleB ? -1 : titleA > titleB ? 1 : 0;
});
$.each(cards, function (index, item) {
$(selector).parent().append(item);
});
}
function updateViews() {
// Handle cards in the list view
$(".home-chronicle-list div.list-container div.card:not(.event)").each(
function () {
if (!$(this).closest(".home-chronicle-block").length) {
var title = $(this).find(".title").detach();
var images = $(this).find(".images").detach();
// Remove existing .title-images if it exists
$(this).find(".title-images").remove();
var titleImagesContainer = $(
'<div class="title-images"></div>'
).append(images, title);
$(this).find(".people").after(titleImagesContainer);
}
}
);
// Handle cards in the block view
$(".home-chronicle-block div.list-container div.card:not(.event)").each(
function () {
// Remove .title-images container if it exists, re-attach .title and .images to their original places
var titleImagesContainer = $(this).find(".title-images");
if (titleImagesContainer.length) {
var title = titleImagesContainer.find(".title").detach();
var images = titleImagesContainer.find(".images").detach();
titleImagesContainer.remove();
$(this).find(".people").after(title);
$(this).find(".type").after(images);
} else {
// If .title-images doesn't exist, ensure .images is placed correctly
var images = $(this).find(".images").detach();
$(this).find(".type").after(images);
}
}
);
}
function processEventCards() {
$(".card.event").each(function () {
var $card = $(this);
var existingContainer = $card.find(".container-people-date");
// Create container if missing
if (existingContainer.length === 0) {
existingContainer = $('<div class="container-people-date"></div>');
$card.append(existingContainer); // temp placement
}
// Detach people and date
var people = $card.find(".people").detach();
var date = $card.find(".date").detach();
// BLOCK VIEW (gallery)
if ($card.closest(".home-chronicle-block").length) {
existingContainer.append(people).append(date);
// Place container after title
if (!existingContainer.is($card.find(".title").next())) {
$card.find(".title").after(existingContainer);
}
// LIST VIEW
} else if ($card.closest(".home-chronicle-list").length) {
// Only append .people into container
existingContainer.empty().append(people);
// Place container before title
$card.find(".title").before(existingContainer);
// Place date after title
$card.find(".title").after(date);
}
});
}
if ($("#home").length > 0) {
// This code will only run only on the homepage.
$(".home-block-view").show();
$(".home-chronicle-block-button, .home-block-view-button").addClass(
"active-view-button"
);
// Initially hide list view sorting buttons and set the default sorted view for block
$(
".home-chronicle-list-button, .home-random-list-button, .home-alphabetical-list-button"
).hide();
sortChronologically(); // Sort the block view chronologically by default
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-list-view-button").click(function () {
$(".home-list-sorting-buttons").css("display", "flex");
// Switching view classes
$(".home-block-view")
.removeClass("home-block-view")
.addClass("home-list-view");
// Additional class switch
$(".home-chronicle-block")
.removeClass("home-chronicle-block")
.addClass("home-chronicle-list");
// Toggling visibility of buttons
$(
".home-chronicle-block-button, .home-random-block-button, .home-alphabetical-block-button"
).hide();
$(
".home-chronicle-list-button, .home-random-list-button, .home-alphabetical-list-button"
).show();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
// Remove active class from block view button and add to list view button
$(".home-block-view-button").removeClass("active-view-button");
$(".home-list-view-button").addClass("active-view-button");
// Conditional checks for transferring the active class from block to list buttons
if ($(".home-chronicle-block-button").hasClass("active-view-button")) {
$(".home-chronicle-block-button").removeClass("active-view-button");
$(".home-chronicle-list-button").addClass("active-view-button");
} else if (
$(".home-random-block-button").hasClass("active-view-button")
) {
$(".home-random-block-button").removeClass("active-view-button");
$(".home-random-list-button").addClass("active-view-button");
} else if (
$(".home-alphabetical-block-button").hasClass("active-view-button")
) {
$(".home-alphabetical-block-button").removeClass("active-view-button");
$(".home-alphabetical-list-button").addClass("active-view-button");
}
});
$(".home-block-view-button").click(function () {
console.log("Block view button clicked.");
$(".home-list-sorting-buttons").hide(); // Hide list sorting buttons
$(".home-list-view")
.removeClass("home-list-view")
.addClass("home-block-view");
$(".home-chronicle-list")
.removeClass("home-chronicle-list")
.addClass("home-chronicle-block");
$(
".home-chronicle-block-button, .home-random-block-button, .home-alphabetical-block-button"
).show();
$(
".home-chronicle-list-button, .home-random-list-button, .home-alphabetical-list-button"
).hide();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-list-view-button").removeClass("active-view-button");
$(".home-block-view-button").addClass("active-view-button");
// Conditional checks for transferring the active class from block to list buttons
if ($(".home-chronicle-list-button").hasClass("active-view-button")) {
$(".home-chronicle-list-button").removeClass("active-view-button");
$(".home-chronicle-block-button").addClass("active-view-button");
} else if ($(".home-random-list-button").hasClass("active-view-button")) {
$(".home-random-list-button").removeClass("active-view-button");
$(".home-random-block-button").addClass("active-view-button");
} else if (
$(".home-alphabetical-list-button").hasClass("active-view-button")
) {
$(".home-alphabetical-list-button").removeClass("active-view-button");
$(".home-alphabetical-block-button").addClass("active-view-button");
}
});
// BLOCK VIEW SORTING BUTTONS
$(".home-chronicle-block-button").click(function () {
sortChronologically();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-chronicle-block-button").addClass("active-view-button");
$(".home-random-block-button").removeClass("active-view-button");
$(".home-alphabetical-block-button").removeClass("active-view-button");
});
$(".home-random-block-button").click(function () {
randomizeCards(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-random-block-button").addClass("active-view-button");
$(".home-chronicle-block-button").removeClass("active-view-button");
$(".home-alphabetical-block-button").removeClass("active-view-button");
});
$(".home-alphabetical-block-button").click(function () {
sortAlphabetically(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-alphabetical-block-button").addClass("active-view-button");
$(".home-chronicle-block-button").removeClass("active-view-button");
$(".home-random-block-button").removeClass("active-view-button");
});
// LIST VIEW SORTING BUTTONS
$(".home-chronicle-list-button").click(function () {
sortChronologically();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-chronicle-list-button").addClass("active-view-button");
$(".home-random-list-button").removeClass("active-view-button");
$(".home-alphabetical-list-button").removeClass("active-view-button");
});
$(".home-random-list-button").click(function () {
randomizeCards(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-random-list-button").addClass("active-view-button");
$(".home-chronicle-list-button").removeClass("active-view-button");
$(".home-alphabetical-list-button").removeClass("active-view-button");
});
$(".home-alphabetical-list-button").click(function () {
sortAlphabetically(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".home-alphabetical-list-button").addClass("active-view-button");
$(".home-chronicle-list-button").removeClass("active-view-button");
$(".home-random-list-button").removeClass("active-view-button");
});
} else {
console.log("NOT HOMEPAGE");
$(".home-list-view").show();
$(".chronicle-list-button, .list-view-button").addClass(
"active-view-button"
);
// Initialization and Default Settings
// Initially hide block view sorting buttons and set the default sorted view for list
$(
".chronicle-block-button, .random-block-button, .alphabetical-block-button"
).hide();
sortChronologically(); // Sort the block view chronologically by default
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".list-view-button").click(function () {
console.log("List view button clicked.");
$(".list-sorting-buttons").css("display", "flex");
$(".block-sorting-buttons").hide();
// Switching view classes
$(".home-block-view")
.removeClass("home-block-view")
.addClass("home-list-view");
// Additional class switch
$(".home-chronicle-block")
.removeClass("home-chronicle-block")
.addClass("home-chronicle-list");
// Toggling visibility of buttons
$(
".chronicle-block-button, .random-block-button, .alphabetical-block-button"
).hide();
$(
".chronicle-list-button, .random-list-button, .alphabetical-list-button"
).show();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
// Remove active class from block view button and add to list view button
$(".block-view-button").removeClass("active-view-button");
$(".list-view-button").addClass("active-view-button");
// Conditional checks for transferring the active class from block to list buttons
if ($(".chronicle-block-button").hasClass("active-view-button")) {
$(".chronicle-block-button").removeClass("active-view-button");
$(".chronicle-list-button").addClass("active-view-button");
} else if ($(".random-block-button").hasClass("active-view-button")) {
$(".random-block-button").removeClass("active-view-button");
$(".random-list-button").addClass("active-view-button");
} else if (
$(".alphabetical-block-button").hasClass("active-view-button")
) {
$(".alphabetical-block-button").removeClass("active-view-button");
$(".alphabetical-list-button").addClass("active-view-button");
}
});
$(".block-view-button").click(function () {
console.log("Block view button clicked.");
$(".list-sorting-buttons").hide(); // Hide list sorting buttons
$(".block-sorting-buttons").css("display", "flex");
$(".home-list-view")
.removeClass("home-list-view")
.addClass("home-block-view");
$(".home-chronicle-list")
.removeClass("home-chronicle-list")
.addClass("home-chronicle-block");
$(
".chronicle-block-button, .random-block-button, .alphabetical-block-button"
).show();
$(
".chronicle-list-button, .random-list-button, .alphabetical-list-button"
).hide();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".list-view-button").removeClass("active-view-button");
$(".block-view-button").addClass("active-view-button");
// Conditional checks for transferring the active class from block to list buttons
if ($(".chronicle-list-button").hasClass("active-view-button")) {
$(".chronicle-list-button").removeClass("active-view-button");
$(".chronicle-block-button").addClass("active-view-button");
} else if ($(".random-list-button").hasClass("active-view-button")) {
$(".random-list-button").removeClass("active-view-button");
$(".random-block-button").addClass("active-view-button");
} else if (
$(".alphabetical-list-button").hasClass("active-view-button")
) {
$(".alphabetical-list-button").removeClass("active-view-button");
$(".alphabetical-block-button").addClass("active-view-button");
}
});
// BLOCK VIEW SORTING BUTTONS
$(".chronicle-block-button").click(function () {
sortChronologically();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".chronicle-block-button").addClass("active-view-button");
$(".random-block-button").removeClass("active-view-button");
$(".alphabetical-block-button").removeClass("active-view-button");
});
$(".random-block-button").click(function () {
randomizeCards(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".random-block-button").addClass("active-view-button");
$(".chronicle-block-button").removeClass("active-view-button");
$(".alphabetical-block-button").removeClass("active-view-button");
});
$(".alphabetical-block-button").click(function () {
sortAlphabetically(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".alphabetical-block-button").addClass("active-view-button");
$(".chronicle-block-button").removeClass("active-view-button");
$(".random-block-button").removeClass("active-view-button");
});
// LIST VIEW SORTING BUTTONS
$(".chronicle-list-button").click(function () {
sortChronologically();
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".chronicle-list-button").addClass("active-view-button");
$(".random-list-button").removeClass("active-view-button");
$(".alphabetical-list-button").removeClass("active-view-button");
});
$(".random-list-button").click(function () {
randomizeCards(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".random-list-button").addClass("active-view-button");
$(".chronicle-list-button").removeClass("active-view-button");
$(".alphabetical-list-button").removeClass("active-view-button");
});
$(".alphabetical-list-button").click(function () {
sortAlphabetically(".list-container .card");
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
$(".alphabetical-list-button").addClass("active-view-button");
$(".chronicle-list-button").removeClass("active-view-button");
$(".random-list-button").removeClass("active-view-button");
});
}
// FILTERS --------------------- SECTION //
// General Filters Toggle Button
$(".general-toggle").click(function () {
var filtersDiv = $("#filters");
var resetButton = $(".reset-button");
filtersDiv.toggleClass("is-visible");
if (filtersDiv.hasClass("is-visible")) {
filtersDiv.css("display", "grid").hide().slideDown(100);
$(this).text("[FILTER]");
// Attach click handler to document
$(document).on("mousedown.hideFilters", function (event) {
var isOutsideFilters =
!filtersDiv.is(event.target) &&
filtersDiv.has(event.target).length === 0;
var isOnToggle = $(event.target).closest(".general-toggle").length > 0;
if (isOutsideFilters && !isOnToggle) {
filtersDiv.removeClass("is-visible").slideUp(100, function () {
$(this).css("display", "none");
});
$(".general-toggle").text("[FILTER]");
// Remove the document click handler
$(document).off("mousedown.hideFilters");
}
});
} else {
filtersDiv.slideUp(100, function () {
$(this).css("display", "none");
});
$(this).text("[FILTER]");
// Remove the document click handler
$(document).off("mousedown.hideFilters");
}
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
});
// Specific Toggle for Filter Sections like TYPE, ENTITY, etc.
$(".open-filter").click(function (event) {
event.stopPropagation();
var filterType = $(this).closest(".filter").data("filter");
var cardSelector = $(".card").length > 0 ? ".card" : ".community-card"; // Determine which card type is present
console.log("Filter type:", filterType, "Card Selector:", cardSelector);
$("#values-" + filterType).toggle();
if ($("#values-" + filterType).is(":visible")) {
$(this).addClass("active-filter");
} else {
$(this).removeClass("active-filter");
}
// Pass the determined card selector to the function
updateLastVisibleCard(cardSelector);
updateWidthBlockView(cardSelector);
processEventCards(cardSelector);
updateViews(cardSelector);
console.log("Updated views and borders after filter toggle");
});
function filterCards() {
var displayCountsHtml = "";
var cardSelector = $(".card").length > 0 ? ".card" : ".community-card"; // Determine which card type is present
$(".filter .values a[title]").each(function () {
var anchor = $(this);
var filterValue = anchor.attr("title").toLowerCase();
var count = 0;
if (anchor.find("button").hasClass("active")) {
$(cardSelector).each(function () {
var card = $(this);
$(".filter").each(function () {
var filterType = $(this).data("filter");
var cardValue = card
.find("." + filterType)
.text()
.toLowerCase();
if (cardValue.indexOf(filterValue) !== -1) {
count++;
}
});
});
displayCountsHtml +=
"<span>[" + count + "] " + filterValue + "</span> ";
}
});
if (displayCountsHtml) {
$(".count-filtered-cards").html(displayCountsHtml).show();
} else {
$(".count-filtered-cards").hide();
}
// Apply filtering and pass the determined card selector to the function
applyFiltering(cardSelector);
updateLastVisibleCard(cardSelector);
updateWidthBlockView(cardSelector);
processEventCards(cardSelector);
updateViews(cardSelector);
console.log("Filtering process complete, updated views and borders");
}
function applyFiltering() {
// Determine which card selector to use based on the elements present in the DOM
var cardSelector = $(".card").length > 0 ? ".card" : ".community-card";
// Apply the logic to the determined card type
$(cardSelector)
.show()
.each(function () {
var card = $(this);
var hideCard = false;
$(".filter").each(function () {
if (hideCard) return;
var filterType = $(this).data("filter");
var activeFilters = $(this)
.find(".values a[title] button.active")
.map(function () {
return $(this).parent("a").attr("title").toLowerCase();
})
.get();
if (activeFilters.length > 0) {
var cardValue = card
.find("." + filterType)
.text()
.toLowerCase();
var matchesFilter = activeFilters.some(function (filterValue) {
return cardValue.indexOf(filterValue) !== -1;
});
if (!matchesFilter) hideCard = true;
}
});
if (hideCard) card.hide();
});
}
function updateLastVisibleCard() {
// Target only the list view container for updating the last visible card
$(".home-chronicle-list div.list-container div.card").removeClass(
"last-visible"
);
// Find the last visible card within the list view and add the class
var lastVisibleCard = $(
".home-chronicle-list div.list-container div.card:visible:last"
);
lastVisibleCard.addClass("last-visible");
}
function updateWidthBlockView() {
// Target only the block view container for updating the with of card
$(".home-chronicle-block div.list-container").css("width", "100%");
$(".home-chronicle-block div.list-container div.card").css(
"width",
"calc(20% - 0px)"
);
$(
".home-chronicle-block div.list-container div.card:nth-child(5n + 1)"
).css("width", "calc(20% + 4px)");
}
// Reset function to remove active filters
$(".reset-filter").click(function (event) {
event.stopPropagation(); // Prevent event bubbling
// Remove 'active' class from all filter buttons
$("#filters .values button").removeClass("active");
$(".open-filter").removeClass("active-filter");
// Reset and hide the filter counts
$(".count-filtered-cards").text("").hide();
filterCards(); // Reapply filtering based on the updated active buttons
// Update other UI elements as needed, excluding the general toggle button
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
});
$("#filters .values button").click(function () {
console.log("Filter is clicked!!!");
$(this).toggleClass("active");
filterCards(); // Re-apply the filters based on the updated active buttons
updateLastVisibleCard();
updateWidthBlockView();
processEventCards();
updateViews();
});
// Hide filters when window is scrolled
$(window).on("scroll", function () {
var filtersDiv = $("#filters");
if (filtersDiv.hasClass("is-visible")) {
filtersDiv.removeClass("is-visible").slideUp(100, function () {
$(this).css("display", "none");
// The filter reset code has been removed to keep the filters active
});
$(".general-toggle").text("[FILTER]"); // Update the toggle button text
}
});
// MODAL ARTICLE --------------------- SECTION //
// Format paragraphs
function formatParagraphs(text) {
var paragraphs = text.split("\n").filter(function (p) {
return p.trim() !== "";
});
return paragraphs
.map(function (p) {
return "<p>" + p.trim() + "</p>";
})
.join("");
}
var images = []; // Initialize an empty array to store the images
// Find all image containers within the article content and extract the necessary information
$(".article-images .image-container").each(function () {
var img = $(this).find("img");
var captionDiv = $(this).find('div[class^="caption-image"]');
var image = {
src: img.attr("src"),
alt: img.attr("alt"),
caption: captionDiv.text(),
captionClass: captionDiv.attr("class"),
};
images.push(image); // Add the image object to the images array
});
if (images.length > 0) {
setupImageToggle(images); // Call the setupImageToggle function with the images array
updateImageLabel(1, images.length); // Set the label for the first image immediately
}
function setupImageToggle(images) {
var currentIndex = 0;
var enableNavigation = images.length > 1; // Enable navigation only if there is more than one image
function showImage(index) {
currentIndex = index;
var image = images[currentIndex];
updateImageLabel(currentIndex + 1, images.length);
$("#article-content")
.find(".article-images")
.html(
getImageHtml(image, currentIndex, images.length, enableNavigation)
);
}
// Attach click handlers only if navigation is enabled
if (enableNavigation) {
$("#article-content").on("click", ".next-arrow", function () {
showImage((currentIndex + 1) % images.length);
});
$("#article-content").on("click", ".prev-arrow", function () {
showImage((currentIndex - 1 + images.length) % images.length);
});
}
// Display the first image
showImage(currentIndex);
}
function getImageHtml(image, currentIndex, totalImages, enableNavigation) {
var imageLabel = currentIndex + 1 + "/" + totalImages + " IMAGES";
// Render navigation arrows based on the enableNavigation flag
var navigationHtml = enableNavigation
? '<div class="prev-arrow"><</div><div class="next-arrow">></div>'
: "";
return (
'<div class="image-navigation">' +
'<p class="article-label-image">' +
imageLabel +
"</p>" +
'<div class="image-container">' +
'<div class="arrows-and-image">' +
navigationHtml +
'<img src="' +
image.src +
'" alt="' +
image.alt +
'">' +
"</div>" +
'<div class="' +
image.captionClass +
'">' +
image.caption +
"</div>" +
"</div>" +
"</div>"
);
}
function updateImageLabel(currentIndex, totalImages) {
var imageLabel = currentIndex + "/" + totalImages + " IMAGES";
$("#article-content .article-label-image").text(imageLabel);
}
$(".caption-image1").each(function () {
// Split the caption at each <br> tag and wrap each line in a span
var htmlContent = $(this).html();
var lines = htmlContent.split("<br>");
var wrappedLines = lines.map(function (line) {
return '<span class="caption-line">' + line + "</span>";
});
var newHtml = wrappedLines.join("<br>");
$(this).html(newHtml);
});
function setShowArticleRotationEffect() {
const offset = 20;
const showArticle = document.querySelector("#show-article");
const h = showArticle.clientHeight;
const theta = -Math.atan(offset / h);
const a = Math.cos(theta);
const b = Math.sin(theta);
const c = -Math.sin(theta);
const d = Math.cos(theta);
const showArticleBefore = document.querySelector("#show-article-before");
const transformValue =
"matrix(" + a + "," + b + "," + c + "," + d + ",0,0)";
showArticleBefore.style.transform = transformValue;
}
function openEvent(element, event) {
event.stopPropagation();
event.preventDefault();
var url = $(element).find(".link a").attr("href");
if (url) {
window.open(url, "_blank").focus();
}
}
function openModal(cardElement, event) {
event.stopPropagation();
var pageTitle = $(cardElement).data("page") || null; // e.g. "090"
window.currentEntryTitle = pageTitle;
var isRelatedArticle = $(cardElement).hasClass("related-article");
showArticleWrapper.css("display", "block");
// Clear existing content in modal
$("#article-title").empty();
$("#article-content").empty();
if (isRelatedArticle) {
// Handle card elements (existing logic)
var cardImages = [];
for (var i = 1; i <= 5; i++) {
var imageClass = ".related-article-image" + i;
var captionClass = ".related-article-caption-image" + i;
var imageElem = $(cardElement).find(imageClass + " img");
if (imageElem.length) {
var captionText = $(cardElement)
.find(imageClass + " " + captionClass)
.text();
cardImages.push({
link: $(cardElement)
.find(imageClass + " a")
.attr("href"),
src: imageElem.attr("src"),
alt: imageElem.attr("alt"),
caption: captionText,
captionClass: "related-article-caption-image" + i,
});
}
}
if (cardImages.length > 1) {
setupImageToggle(cardImages);
}
// Handle related-article elements
var entryNumber = $(cardElement)
.find(".related-article-entry-number")
.text();
var peopleHtml = $(cardElement).find(".related-article-people").html();
var title = $(cardElement).find(".related-article-title").text();
var typeHtml = $(cardElement).find(".related-article-type").html();
var externalPdfURL = $(cardElement)
.find(".related-article-pdf a")
.attr("href");
var externalLinkURL = $(cardElement)
.find(".related-article-link a")
.attr("href");
var entity = $(cardElement).find(".related-article-entity").text();
var discipline = $(cardElement)
.find(".related-article-discipline")
.text();
var subjectHtml = $(cardElement).find(".related-article-subject").html();
var description = $(cardElement)
.find(".related-article-description")
.html();
var reflection = $(cardElement)
.find(".related-article-reflection")
.html();
var quote = $(cardElement).find(".related-article-quote").text();
var modificationDate = $(cardElement)
.find(".related-article-modification-date")
.text();
// Update modal content for related-article
$("#article-title").html(
'<p class="article-entry-number">' +
entryNumber +
'</p><p class="article-people">' +
peopleHtml +
"</p>"
);
var articleContentHtml = '<div class="article-title-link">';
articleContentHtml += '<p class="article-title">' + title + "</p>";
// Create a div that will wrap the links
articleContentHtml += '<div class="link-pdf">';
if (externalPdfURL) {
articleContentHtml +=
'<a href="' +
externalPdfURL +
'" target="_blank" class="pdf-link-icon">[PDF<span class="text-symbol">⤴</span>]</a>';
}
if (externalLinkURL) {
articleContentHtml +=
'<a href="' +
externalLinkURL +
'" target="_blank" class="external-link-icon">[WEB<span class="text-symbol">⤴</span>]</a>';
}
// Close the .link-pdf div
articleContentHtml += "</div>";
articleContentHtml += "</div>"; // Close the container div
// Append type, entity, discipline, and subject details
articleContentHtml +=
'<p class="article-type">' +
typeHtml +
"</p>" +
'<div class="article-metadata">' +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Entity</p>' +
'<p class="article-metadata-value">' +
entity +
"</p>" +
"</div>" +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Discipline</p>' +
'<p class="article-metadata-value">' +
discipline +
"</p>" +
"</div>" +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Subject(s)</p>' +
'<p class="article-metadata-value">' +
subjectHtml +
"</p>" +
"</div>" +
"</div>";
// Add images if any
if (cardImages.length > 0) {
var initialImage = cardImages[0]; // Use the first image initially
var enableNavigation = cardImages.length > 1; // Enable navigation only if more than one image
articleContentHtml +=
'<div class="article-images">' +
getImageHtml(initialImage, 0, cardImages.length, enableNavigation) +
"</div>";
}
// Add non-image content (description, reflection, etc.)
articleContentHtml +=
(description
? '<p class="article-label-description">Description</p>' +
'<div class="article-description">' +
formatParagraphs(description) +
"</div>"
: "") +
(reflection
? '<p class="article-label-reflection">Reflection</p>' +
'<div class="article-reflection">' +
formatParagraphs(reflection) +
"</div>"
: "") +
(quote
? '<p class="article-label-quote">Quote</p>' +
'<p class="article-quote">' +
quote +
"</p>"
: "") +
'<p class="article-label-modification-date">Added on</p>' +
'<div class="article-modification-date">' +
modificationDate +
"</div>";
$("#article-content").html(articleContentHtml);
} else {
// Handle card elements (existing logic)
var cardImages = [];
for (var i = 1; i <= 5; i++) {
var imageClass = ".image" + i;
var captionClass = ".caption-image" + i;
var imageElem = $(cardElement).find(imageClass + " img");
if (imageElem.length) {
var captionText = $(cardElement)
.find(imageClass + " " + captionClass)
.text();
cardImages.push({
link: $(cardElement)
.find(imageClass + " a")
.attr("href"),
src: imageElem.attr("src"),
alt: imageElem.attr("alt"),
caption: captionText,
captionClass: "caption-image" + i,
});
}
}
if (cardImages.length > 1) {
setupImageToggle(cardImages);
}
var entryNumber = $(cardElement).find(".entry-number").text();
var title = $(cardElement).find(".title").text();
var peopleHtml = $(cardElement).find(".people").html();
var typeHtml = $(cardElement).find(".type").html();
var externalPdfURL = $(cardElement).find(".pdf a").attr("href");
var externalLinkURL = $(cardElement).find(".link a").attr("href");
var entity = $(cardElement).find(".entity").text();
var discipline = $(cardElement).find(".discipline").text();
var subjectHtml = $(cardElement).find(".subject").html();
var description = $(cardElement).find(".description").html();
var reflection = $(cardElement).find(".reflection").html();
var quote = $(cardElement).find(".quote").text();
var externalReferenceHtml = $(cardElement)
.find(".external-reference")
.html();
var modificationDate = $(cardElement).find(".modification-date").text();
var relatedArticlesHtml = $(cardElement).find(".related-articles").html();
$("#article-title").html(
'<p class="article-entry-number">' +
entryNumber +
'</p><p class="article-people">' +
peopleHtml +
"</p>"
);
var articleContentHtml = '<div class="article-title-link">';
articleContentHtml += '<p class="article-title">' + title + "</p>";
// Create a div that will wrap the links
articleContentHtml += '<div class="link-pdf">';
if (externalPdfURL) {
articleContentHtml +=
'<a href="' +
externalPdfURL +
'" target="_blank" class="pdf-link-icon">[PDF<span class="text-symbol">⤴</span>]</a>';
}
if (externalLinkURL) {
articleContentHtml +=
'<a href="' +
externalLinkURL +
'" target="_blank" class="external-link-icon">[WEB<span class="text-symbol">⤴</span>]</a>';
}
// Close the .link-pdf div
articleContentHtml += "</div>";
articleContentHtml += "</div>"; // Close the new div
// Append type, entity, discipline, and subject details
articleContentHtml +=
'<p class="article-type">' +
typeHtml +
"</p>" +
'<div class="article-metadata">' +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Entity</p>' +
'<p class="article-metadata-value">' +
entity +
"</p>" +
"</div>" +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Discipline</p>' +
'<p class="article-metadata-value">' +
discipline +
"</p>" +
"</div>" +
'<div class="article-metadata-column">' +
'<p class="article-metadata-label">Subject(s)</p>' +
'<p class="article-metadata-value">' +
subjectHtml +
"</p>" +
"</div>" +
"</div>";
// Add images if any
if (cardImages.length > 0) {
var initialImage = cardImages[0]; // Use the first image initially
var enableNavigation = cardImages.length > 1; // Enable navigation only if more than one image
articleContentHtml +=
'<div class="article-images">' +
getImageHtml(initialImage, 0, cardImages.length, enableNavigation) +
"</div>";
}
// Add non-image content (description, reflection, etc.)
articleContentHtml +=
(description
? '<p class="article-label-description">Description</p>' +
'<div class="article-description">' +
formatParagraphs(description) +
"</div>"
: "") +
(reflection
? '<p class="article-label-reflection">Reflection</p>' +
'<div class="article-reflection">' +
formatParagraphs(reflection) +
"</div>"
: "") +
(externalReferenceHtml
? '<p class="article-label-external-reference">References</p>' +
'<p class="article-external-reference">' +
externalReferenceHtml +
"</p>"
: "") +
(quote
? '<p class="article-label-quote">Quote</p>' +
'<p class="article-quote">' +
quote +
"</p>"
: "") +
'<p class="article-label-modification-date">Added on</p>' +
'<div class="article-modification-date">' +
modificationDate +
"</div>";
$("#article-content").html(articleContentHtml);
$("#related-articles").html(relatedArticlesHtml);
if (relatedArticlesHtml && relatedArticlesHtml.trim().length > 0) {
$("#related-articles")
.html(
'<div class="related-articles-label">Related Articles</div><div class="related-articles-container">' +
relatedArticlesHtml +
"</div>"
)
.show();
}
}
// Check which view is active and set the width accordingly
if ($(".home-chronicle-list").is(":visible")) {
$(".home-list-view").each(function () {
var currentWidth = $(this).width(); // Get the current width
$(this).data("originalWidth", currentWidth); // Store the original width
$(this).css("width", "calc(60% - 2px)");
});
// Modify the .type elements within .home-chronicle-list
$(".home-chronicle-list .type").each(function () {
var currentLeft = $(this).css("left"); // Get the current left value
$(this).data("originalLeft", currentLeft); // Store the original left value
$(this).css("left", "85%");
});
} else if ($(".home-chronicle-block").is(":visible")) {
$(".home-chronicle-block div.list-container").each(function () {
var currentWidth = $(this).width(); // Get the current width
$(this).css("width", "calc(60% - 0px)"); // Set the new width as 30% of the current width
});
$(".home-chronicle-block div.list-container div.card").each(function () {
var currentWidth = $(this).width(); // Get the current width
$(this).css("width", "calc(33.333% - 0px)"); // Set the new width as 30% of the current width
});
}
// Apply the fade-out effect to both #list and #list-list elements
$(".list-container").addClass("fade-out");
}
// closeModal function
function closeModal() {
if ($(".home-chronicle-list").is(":visible")) {
$(".home-list-view").css("width", "100%");
$(".home-chronicle-list div.list-container div.card div.type").css(
"left",
"90%"
);
} else if ($(".home-chronicle-block").is(":visible")) {
updateWidthBlockView();
}
showArticleWrapper.hide();
}
$(".card").on("click", function (event) {
// Check if the click event is originating from a link within .people or .type, or any other specific area
if ($(event.target).closest(".people a, .type a").length) {
// The click is inside a link; let the default behavior proceed without opening the modal
return;
}
// Prevent further event handling if the card has the 'event' class
if ($(this).hasClass("event")) {
event.stopImmediatePropagation();
openEvent(this, event);
$(".list-container").removeClass("fade-out");
closeModal();
} else {
// Handle cards without the 'event' class
openModal(this, event);
setShowArticleRotationEffect();
}
});
$("#show-article-wrapper").on("click", ".related-article", function (event) {
openModal(this, event); // Call openModal when a related-article is clicked
setShowArticleRotationEffect();
});
// --- PRINT HELPERS ---
// Warm the font cache in the *parent* document.
function preloadFontForPrint() {
var link = document.createElement("link");
link.rel = "preload";
link.as = "font";
link.type = "font/woff2";
link.href = "/fonts/HALColant-TextRegular.woff2?v=20250820";
link.crossOrigin = "anonymous";
document.head.appendChild(link);
// keep it; no need to remove
}
// Simple cache buster
function cacheBust(url) {
return url + (url.indexOf("?") > -1 ? "&" : "?") + "_=" + Date.now();
}
// --- tiny inline chooser for border preference ---
function ensurePrintChooser() {
var $chooser = $("#print-chooser");
if ($chooser.length) return $chooser;
// MediaWiki-safe: use <div> + <a>, no <button> needed
$chooser = $(
'<div id="print-chooser" class="print-chooser" style="display:none;">' +
'<a href="#" id="print-with-border" class="print-choice">[with border]</a> ' +
'<a href="#" id="print-no-border" class="print-choice">[no border]</a>' +
"</div>"
);
$("#print-button").after($chooser);
return $chooser;
}
// Kill any previous print handlers
$(document).off(
"click.print",
"#print-button, #print-with-border, #print-no-border"
);
// One handler for all three
$(document).on(
"click.print",
"#print-button, #print-with-border, #print-no-border",
function (e) {
e.preventDefault();
var id = this.id;
// If the main [print] is clicked, just toggle the chooser and stop.
if (id === "print-button") {
var $chooser = ensurePrintChooser();
$chooser.toggle();
return; // <-- don't start printing yet
}
// otherwise it's one of the two choices; proceed with your existing flow…
var $btn = $(this);
if ($btn.data("busy")) return;
$btn.data("busy", true);
// decide the border preference from the clicked button id
var borderPref = id === "print-no-border" ? "without" : "with";
console.log("[print] option chosen:", borderPref);
preloadFontForPrint();
var title = window.currentEntryTitle; // e.g. "090"
if (!title) {
console.warn("[print] no currentEntryTitle");
window.print();
$btn.data("busy", false);
return;
}
var pageUrl = mw.util.getUrl(title);
var pageUrlFresh = cacheBust(pageUrl);
console.log("[print] fetching page HTML:", pageUrlFresh);
$.get(pageUrlFresh)
.done(function (html) {
var $tmp = $("<div>").html(html);
var $print = $tmp.find(".print-only").first();
console.log("[print] .print-only found:", $print.length);
if (!$print.length) {
console.warn("[print] no .print-only found; fallback print");
window.print();
$btn.data("busy", false);
return;
}
// Build hidden iframe
var iframe = document.createElement("iframe");
iframe.style.position = "fixed";
iframe.style.right = "0";
iframe.style.bottom = "0";
iframe.style.width = "0";
iframe.style.height = "0";
iframe.style.border = "0";
document.body.appendChild(iframe);
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(
'<!doctype html><html><head><meta charset="utf-8"><title>Print</title></head><body></body></html>'
);
doc.close();
// Ensure relative URLs (fonts/images) resolve inside iframe
var base = doc.createElement("base");
base.href = location.origin + "/";
doc.head.appendChild(base);
// Inject PRINT CSS (cache-busted) and await it
var printCssUrl =
"/index.php?title=MediaWiki:Print.css&action=raw&ctype=text/css";
var printCssFresh = cacheBust(printCssUrl);
var linkCss = doc.createElement("link");
linkCss.rel = "stylesheet";
linkCss.href = printCssFresh;
var cssLoaded = new Promise(function (resolve) {
linkCss.onload = function () {
resolve();
};
linkCss.onerror = function () {
console.warn("[print] CSS failed to load");
resolve();
}; // don't block
});
// Preload the font *inside* iframe (Chrome becomes much happier)
var linkFont = doc.createElement("link");
linkFont.rel = "preload";
linkFont.as = "font";
linkFont.type = "font/woff2";
linkFont.href = "/fonts/HALColant-TextRegular.woff2?v=20250820";
linkFont.crossOrigin = "anonymous";
doc.head.appendChild(linkFont);
doc.head.appendChild(linkCss);
// Inject the printable HTML
doc.body.innerHTML = $print.prop("outerHTML");
// >>> INSERTED: apply border preference as a class on the iframe document
(function applyBorderPreference() {
var root = doc.documentElement;
if (borderPref === "without") {
if (root.classList) root.classList.add("print-no-border");
else if (!/\bprint-no-border\b/.test(root.className))
root.className += " print-no-border";
} else {
if (root.classList) root.classList.remove("print-no-border");
else
root.className = root.className.replace(
/\bprint-no-border\b/g,
""
);
}
})();
// Remove “empty” optional sections so they don’t leave gaps in print.
// --- CLEAN: remove empty paragraphs/whitespace nodes that create phantom gaps
(function () {
// 1) Drop <p> that are visually empty or only /whitespace
var ps = doc.querySelectorAll("#article-content p");
Array.prototype.forEach.call(ps, function (p) {
var txt = (p.textContent || "").replace(/\u00a0/g, " ").trim();
// also ignore spans that were left with only <br>
var onlyBr =
p.children.length === 1 && p.firstElementChild.tagName === "BR";
if (
(!txt &&
!p.querySelector("img, a, strong, em, span:not(:empty)")) ||
onlyBr
) {
p.parentNode && p.parentNode.removeChild(p);
}
});
// 2) Remove pure-whitespace text nodes directly under #article-content
var root = doc.getElementById("article-content");
if (root) {
Array.prototype.slice.call(root.childNodes).forEach(function (n) {
if (n.nodeType === 3 && !n.textContent.replace(/\s+/g, "")) {
root.removeChild(n);
}
});
}
})();
(function () {
var css =
"@media print{" +
// Paragraphs inside rich text
" .article-description p,.article-reflection p,.article-external-reference p,.article-quote p{margin:0 0 1.2mm!important;}" +
" .article-description p:last-child,.article-reflection p:last-child,.article-external-reference p:last-child,.article-quote p:last-child{margin-bottom:0!important;}" +
// Ruled sections: one consistent bottom padding for the hairline
" .article-entry-number,.link-pdf,.article-type,.article-metadata,.article-images,.article-description,.article-reflection,.article-external-reference,.article-quote,.article-mod-line{padding-bottom:1mm!important;}" +
// Labels: zero their default margin, then add ONE spacer when following any ruled block
' [class^="article-label-"]{margin-top:0!important;}' +
// <<< NEW: spacer no matter which section precedes (handles skipped sections)
' .article-entry-number + [class^="article-label-"],' +
' .link-pdf + [class^="article-label-"],' +
' .article-type + [class^="article-label-"],' +
' .article-metadata + [class^="article-label-"],' +
' .article-images + [class^="article-label-"],' +
' .article-description + [class^="article-label-"],' +
' .article-reflection + [class^="article-label-"],' +
' .article-external-reference + [class^="article-label-"],' +
' .article-quote + [class^="article-label-"],' +
' .article-mod-line + [class^="article-label-"]{margin-top:0.9mm!important;}' +
// No gap between any label and its own body
" .article-label-description + .article-description," +
" .article-label-reflection + .article-reflection," +
" .article-label-external-reference + .article-external-reference," +
" .article-label-quote + .article-quote," +
" .article-label-modification-date + .article-modification-date{margin-top:0!important;}" +
// Title/link row cleanup
" .article-title-link{margin:0!important;padding:0!important;}" +
" .article-title-link > *{margin:0!important;}" +
" .link-pdf{margin-top:0!important;}" +
// Final block: no trailing hairline
" #article-content > :last-child{padding-bottom:0!important;}" +
" #article-content > :last-child::after{content:none!important;}" +
"}";
var style = doc.createElement("style");
style.type = "text/css";
style.appendChild(doc.createTextNode(css));
doc.head.appendChild(style);
})();
// --- PDF-friendly links for Chrome on macOS ---
// 1) Add a tiny print-only CSS override to keep anchors as one box.
var linkCssFix = doc.createElement("style");
linkCssFix.textContent =
"@media print {\n" +
" /* Keep anchor boxes intact so Chrome preserves the PDF annotation */\n" +
" .article-external-reference a,\n" +
" .link-pdf a {\n" +
" white-space: nowrap !important;\n" +
" word-break: normal !important;\n" +
" overflow-wrap: normal !important;\n" +
" text-decoration: underline;\n" +
" }\n" +
" /* Allow wrapping outside the anchor instead */\n" +
" .article-external-reference {\n" +
" overflow-wrap: anywhere;\n" +
" word-break: break-word;\n" +
" }\n" +
" /* Defensive: make sure anchors have a box */\n" +
" a[href] { position: relative; }\n" +
"}\n";
doc.head.appendChild(linkCssFix);
// 2) Normalize long link text so it doesn't force wrapping inside anchors.
(function () {
// Shorten long visible URLs in external references, keep href intact
var refs = doc.querySelectorAll(
".article-external-reference a[href]"
);
refs.forEach(function (a) {
var txt = (a.textContent || "").trim();
var href = a.getAttribute("href") || "";
var looksLongUrl = /^https?:\/\//i.test(txt) && txt.length > 60;
if (looksLongUrl) {
try {
var u = new URL(href, doc.baseURI);
var label =
u.hostname +
(u.pathname.replace(/\/$/, "") ? u.pathname : "");
if (label.length > 40) label = label.slice(0, 37) + "…";
a.textContent = label;
} catch (e) {
a.textContent = "Link";
}
}
// Ensure single-box anchors
a.style.whiteSpace = "nowrap";
a.style.wordBreak = "normal";
a.style.overflowWrap = "normal";
});
// Icon links ([PDF⤴] [WEB⤴]) are short; still enforce single-box
doc.querySelectorAll(".link-pdf a[href]").forEach(function (a) {
a.style.whiteSpace = "nowrap";
a.style.wordBreak = "normal";
a.style.overflowWrap = "normal";
});
})();
// Wait helpers
function waitImages() {
var imgs = [].slice.call(doc.images || []);
if (!imgs.length) return Promise.resolve();
return Promise.all(
imgs.map(function (img) {
if (img.decode) {
try {
return img.decode().catch(function () {});
} catch (e) {}
}
return new Promise(function (res) {
if (img.complete) return res();
img.onload = img.onerror = function () {
res();
};
});
})
);
}
function waitFonts(timeoutMs) {
if (!doc.fonts || !doc.fonts.ready) return Promise.resolve();
var ready = doc.fonts.ready;
var t = new Promise(function (res) {
setTimeout(res, timeoutMs || 1200);
});
return Promise.race([ready, t]);
}
// **Load the specific face** so Chrome actually uses it
function waitSpecificFont(timeoutMs) {
if (!doc.fonts || !doc.fonts.load) return Promise.resolve();
var p = Promise.all([
doc.fonts.load('400 16px "HALColant-TextRegular"'),
doc.fonts.load('normal 16px "HALColant-TextRegular"'),
]);
var t = new Promise(function (res) {
setTimeout(res, timeoutMs || 1200);
});
return Promise.race([p, t]);
}
function nextFrame() {
return new Promise(function (res) {
(
iframe.contentWindow.requestAnimationFrame || setTimeout
)(res, 0);
});
}
Promise.all([
cssLoaded,
waitImages(),
waitFonts(1200),
waitSpecificFont(1200),
nextFrame(),
]).then(function () {
try {
// build the desired PDF filename via document.title
var entryNum = "";
var numEl = doc.querySelector(".article-entry-number");
if (numEl) {
var m = (numEl.textContent || "").match(/\d+/);
entryNum = m ? m[0] : "";
}
var desiredTitle =
(entryNum ? entryNum + "." : "") + "softwear.directory";
// save originals (scoped here)
var oldIframeTitle = doc.title;
var oldParentTitle = document.title;
// define onafterprint AFTER we have originals so it can close over them
iframe.contentWindow.onafterprint = function () {
try {
doc.title = oldIframeTitle; // restore iframe doc title
document.title = oldParentTitle; // restore parent title
} catch (e) {}
setTimeout(function () {
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
}, 100);
$btn.data("busy", false);
};
// set temporary titles used by Chrome for the default PDF name
doc.title = desiredTitle; // iframe document
// (next line is optional/redundant; doc === iframe.contentWindow.document)
// iframe.contentWindow.document.title = desiredTitle;
document.title = desiredTitle; // parent (helps on some setups)
// print
iframe.contentWindow.focus();
iframe.contentWindow.print();
// fallback cleanup in case onafterprint doesn’t fire
setTimeout(function () {
try {
doc.title = oldIframeTitle;
document.title = oldParentTitle;
} catch (e) {}
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
$btn.data("busy", false);
}, 1000);
} catch (err) {
console.warn("[print] failed before print:", err);
$btn.data("busy", false);
}
});
})
.fail(function (xhr) {
console.warn(
"[print] fetch failed:",
xhr && xhr.status,
xhr && xhr.statusText
);
window.print();
$("#print-button").data("busy", false);
});
}
);
// Close modal with Close button
$("#close-button").on("click", function () {
$(".list-container").removeClass("fade-out");
closeModal();
});
// Close modal and remove fade out also when clicking outside of card
$(document).on("mousedown", function (event) {
var isOutsideWrapper =
!showArticleWrapper.is(event.target) &&
showArticleWrapper.has(event.target).length === 0;
var isOnCard = $(event.target).closest(".card, .list-card").length > 0;
if (!areFiltersActive) {
if (isOutsideWrapper && !isOnCard) {
$(".list-container").removeClass("fade-out");
showArticleWrapper.css("display", "none");
closeModal(); // Use closeModal() for cleanup
}
}
});
// Hover effect for scrolling
$("#show-article-wrapper").hover(
function () {
// On hover, enable scrolling on #show-article-wrapper
$(this).css("overflow-y", "auto");
$(this).css("overflow-x", "hidden");
},
function () {
// On hover out, disable scrolling on #show-article-wrapper
$(this).css("overflow-y", "hidden");
$(this).css("overflow-x", "hidden");
}
);
// Format community card, when in the Community Entries page
if ($(".community-card").length) {
formatCommunityCardDescriptions();
}
function formatCommunityCardDescriptions() {
$(".community-card").each(function () {
// Format paragraphs in community-description
var descriptionContainer = $(this).find(".community-description");
var rawDescription = descriptionContainer.text();
var formattedDescription = formatParagraphs(rawDescription);
descriptionContainer.html(formattedDescription);
// Remove empty elements in the entire card
$(this)
.find("*")
.each(function () {
if ($(this).is(":empty") || $(this).html().trim() === "<br>") {
$(this).remove();
}
});
});
}
if ($("#show-article-wrapper-entry").length) {
// Your existing formatParagraphs function
function formatParagraphs(text) {
var paragraphs = text.split("\n").filter(function (p) {
return p.trim() !== "";
});
return paragraphs
.map(function (p) {
return "<p>" + p.trim() + "</p>";
})
.join("");
}
// Check if ".article-description" exists and format its text
if ($(".article-description").length) {
var descriptionText = $(".article-description").text();
var formattedDescription = formatParagraphs(descriptionText);
$(".article-description").html(formattedDescription); // Set the formatted text
}
// Check if ".article-reflection" exists and format its text
if ($(".article-reflection").length) {
var reflectionText = $(".article-reflection").text();
var formattedReflection = formatParagraphs(reflectionText);
$(".article-reflection").html(formattedReflection); // Set the formatted text
}
}
// SEARCH --------------------- SECTION //
// Check if div with class "mw-search-results-info" exists
if ($(".mw-search-results-info").length) {
// Select the child <p> element and check its content
var $paragraph = $(".mw-search-results-info > p");
var currentText = $paragraph.text().trim();
// Check if the current text is not "There were no results matching the query."
if (currentText !== "There were no results matching the query.") {
// Overwrite the content with "Search results"
$paragraph.text("Pages related to your Search");
}
}
// Object to store encountered titles
var encounteredTitles = {};
// Iterate over each search result
$(".mw-search-result-heading").each(function () {
// Get the title of the current search result
var title = $(this).find("a").attr("title");
// Check if the title has already been encountered
if (encounteredTitles[title]) {
// Hide the duplicate search result
$(this).hide();
} else {
// Mark the title as encountered
encounteredTitles[title] = true;
}
});
// Remove unwanted white spaces between lines
$(".mw-search-results-container")
.contents()
.filter(function () {
return this.nodeType === 3; // Filter text nodes
})
.remove();
// Edits regarding Search Results
// Define the new form HTML as a string
var newFormHtml =
'<form action="/index.php" id="searchform">' +
'<div id="simpleSearchSpecial" class="right-inner-addon">' +
"<span>[ Search ]</span>" +
'<input class="form-control" name="search" placeholder="" title="Search [alt-shift-f]" accesskey="f" id="searchInput" tabindex="1" autocomplete="off" type="search">' +
'<span class="closing-bracket">]</span>' +
'<input value="Special:Search" name="title" type="hidden">' +
"</div>" +
"</form>";
// Replace the div with id="searchText" with the new form
$("#searchText").replaceWith(newFormHtml);
// Target the button based on its complex class structure
$(".oo-ui-actionFieldLayout-button .oo-ui-buttonInputWidget").remove();
// Check if #submit button exists and add event listener if it does
var submitButton = document.querySelector("#submit");
if (submitButton) {
// Add click event listener
submitButton.addEventListener("click", function (event) {
event.preventDefault(); // Prevent the default link behavior
var email = "submit@softwear.directory";
var subject = "new entry to the softwear directory";
var body =
"☺ the following content could be interesting for the directory:\n\n" +
"[ author / creator ]\n\n" +
"---\n\n" +
"[ title ]\n\n" +
"---\n\n" +
"[ why should it be included? ]\n\n" +
"---\n\n" +
"[ link or pdf ]\n\n" +
"---\n\n" +
"[ your name / contact / social ]\n\n" +
"---";
var mailtoLink =
"mailto:" +
encodeURIComponent(email) +
"?subject=" +
encodeURIComponent(subject) +
"&body=" +
encodeURIComponent(body).replace(/%20/g, " ");
window.location.href = mailtoLink;
});
}
// Tooltip for "wander elsewhere..." on .card.event
var tooltip = $(
'<div class="tooltip-popup">wander elsewhere...</div>'
).appendTo("body");
$(".card.event").on("mouseenter", function () {
tooltip.css("opacity", 1);
});
$(".card.event").on("mousemove", function (e) {
var offsetX = 10; // right of cursor
var offsetY = -30; // above cursor
tooltip.css({
left: e.clientX + offsetX + "px",
top: e.clientY + offsetY + "px",
});
});
$(".card.event").on("mouseleave", function () {
tooltip.css("opacity", 0);
});
mw.loader.using("mediawiki.api", function () {
// Only run on form edit page
if (mw.config.get("wgCanonicalSpecialPageName") === "FormEdit") {
new mw.Api()
.post({
action: "purge",
titles: "Main",
})
.fail(function (err) {
// Optional: leave a minimal fallback error log
console.warn("Main page purge failed", err);
});
}
});
});