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) { console.log("The #home element exists on this page."); // This code will only run only on the homepage. // Show the block view container once everything is set up $(".home-block-view").show(); $(".home-chronicle-block-button, .home-block-view-button").addClass( "active-view-button" ); // Initialization and Default Settings // 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 () { console.log("List view button clicked."); $(".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(); } // Kill any previous print handlers $(document).off("click.print", "#print-button"); $(document).on("click.print", "#print-button", function () { // debounce to avoid double/racing prints var $btn = $("#print-button"); if ($btn.data("busy")) return; $btn.data("busy", true); 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"); // Wait helpers function waitImages() { var imgs = Array.from(doc.images || []); if (!imgs.length) return Promise.resolve(); return Promise.all( imgs.map(function (img) { if (img.decode) return img.decode().catch(function () {}); // ignore decode failures 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); }); } // Extra cleanup guard (Chrome sometimes delays afterprint) iframe.contentWindow.onafterprint = function () { setTimeout(function () { if (iframe.parentNode) iframe.parentNode.removeChild(iframe); }, 100); $btn.data("busy", false); }; Promise.all([ cssLoaded, waitImages(), waitFonts(1200), waitSpecificFont(1200), nextFrame(), // settle layout ]).then(async function () { try { // === Dynamically set page height to match content === function pxToMm(px) { return (px * 25.4) / 96; } // 1) Locate wrapper inside the print iframe var wrapper = doc.querySelector(".entry-wrapper.print-a4-narrow") || doc.querySelector(".print-only") || doc.body; // Force reflow void wrapper.offsetHeight; // 2) Measure height in px var contentPx = wrapper.scrollHeight; var contentMm = Math.ceil(pxToMm(contentPx) + 2); // +2mm buffer // 3) Account for @page margins (12mm top + bottom) var topBottomMarginsMm = 24; var targetPageMm = contentMm + topBottomMarginsMm; // 4) Clamp so it never exceeds A4 height (297mm), // but don’t go below a minimal height either targetPageMm = Math.min(Math.max(targetPageMm, 120), 297); // 5) Inject overriding @page rule var dyn = doc.createElement("style"); dyn.setAttribute("id", "dynamic-print-size"); dyn.textContent = "@page { size: 93mm " + targetPageMm + "mm; margin: 12mm; }"; doc.head.appendChild(dyn); // 6) Let the iframe layout with the new page size await new Promise(function (res) { ( iframe.contentWindow.requestAnimationFrame || setTimeout )(res, 0); }); // 7) Print! iframe.contentWindow.focus(); iframe.contentWindow.print(); } catch (e) { console.warn("[print] dynamic sizing failed:", e); iframe.contentWindow.focus(); iframe.contentWindow.print(); } finally { // fallback cleanup in case onafterprint doesn’t fire setTimeout(function () { if (iframe.parentNode) iframe.parentNode.removeChild(iframe); $btn.data("busy", false); }, 1000); } }); }) .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(); } }); }); } // NRS ENTRIES --------------------- SECTION // console.log("Document ready!"); // Check if document ready event is triggered if ($("#show-article-wrapper-entry").length) { console.log("Element with id 'show-article-wrapper-entry' found!"); // Check if the target element exists // 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"); console.log("Submit button:", submitButton); if (submitButton) { console.log("#submit button found."); // Add click event listener submitButton.addEventListener("click", function (event) { console.log("Submit button clicked."); 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); }); } }); });