MediaWiki: Common.js: Difference between revisions
From Psalms: Layer by Layer
mNo edit summary |
mNo edit summary |
||
Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
// Function to check if all <pre class="mermaid"> elements are processed | |||
function checkMermaidProcessed() { | |||
var mermaidPreElements = document.querySelectorAll('pre.mermaid'); | |||
var allProcessed = true; | |||
mermaidPreElements.forEach(function (element) { | |||
if (!element.hasAttribute('data-processed') || element.getAttribute('data-processed') !== 'true') { | |||
allProcessed = false; | |||
} | |||
}); | |||
return allProcessed; | |||
} | |||
// Function to wait until all Mermaid diagrams are processed | |||
function waitForMermaidProcessing(callback) { | |||
var interval = setInterval(function () { | |||
if (checkMermaidProcessed()) { | |||
clearInterval(interval); | |||
callback(); // Once all elements are processed, run the callback | |||
} | |||
}, 100); // Check every 100ms | |||
} | |||
function toggleVisibility(containerId, className) { | function toggleVisibility(containerId, className) { | ||
console.log("Toggling visibility for " + className + " in " + containerId); | //console.log("Toggling visibility for " + className + " in " + containerId); | ||
var container = document.getElementById(containerId); | var container = document.getElementById(containerId); | ||
if (container) { | if (container) { | ||
Line 21: | Line 45: | ||
function attachToggleListeners() { | function attachToggleListeners() { | ||
// | //console.log("Attaching event listeners to toggle links."); | ||
var toggleLinks = document.querySelectorAll("[data-container-id][data-class]"); | var toggleLinks = document.querySelectorAll("[data-container-id][data-class]"); | ||
// console.log("Found " + toggleLinks.length + " links."); | //console.log("Found " + toggleLinks.length + " links."); | ||
// If no toggle links are found, print a warning | |||
if (toggleLinks.length === 0) { | |||
console.warn("No toggle links found on the page."); | |||
} | |||
for (var i = 0; i < toggleLinks.length; i++) { | for (var i = 0; i < toggleLinks.length; i++) { | ||
(function (toggleLink) { | (function (toggleLink) { | ||
Line 36: | Line 66: | ||
} | } | ||
// =========================== | |||
$(document).ready(function () { | |||
//console.log("Document ready. Attaching event listeners to toggle links."); | |||
// Now attach event listeners for toggling visibility | |||
attachToggleListeners(); | |||
// Wait until all Mermaid diagrams are processed | |||
waitForMermaidProcessing(function () { | |||
//console.log("Mermaid diagrams are fully processed."); | |||
$('div[id^="verse-"]').each(function () { | |||
var parentDiv = $(this); | |||
$('div[id^="verse-"]').each(function() { | |||
var parentDiv = $(this); | |||
var svg = parentDiv.find('svg'); | var svg = parentDiv.find('svg'); | ||
var panZoomInstance; | var panZoomInstance; | ||
Line 93: | Line 105: | ||
}); | }); | ||
panZoomInstance = svgPanZoom(svg[0], { | panZoomInstance = svgPanZoom(svg[0], { | ||
panEnabled: true, | panEnabled: true, | ||
Line 104: | Line 115: | ||
}); | }); | ||
// | // Resize handler to keep SVG scaled on window resize | ||
var resizeHandler = function() { | var resizeHandler = function () { | ||
var newWidth = preElement.width(); | var newWidth = preElement.width(); | ||
var newHeight = preElement.height(); | var newHeight = preElement.height(); | ||
console.log('pre.mermaid container resized to: ', newWidth, newHeight); | //console.log('pre.mermaid container resized to: ', newWidth, newHeight); | ||
var newScaleX = newWidth / viewBoxWidth; | var newScaleX = newWidth / viewBoxWidth; | ||
Line 118: | Line 129: | ||
'max-width': (newWidth) + 'px' | 'max-width': (newWidth) + 'px' | ||
//'height': (viewBoxHeight * newScale) + 'px' | //'height': (viewBoxHeight * newScale) + 'px' | ||
// Do not change the height to avoid reflowing the html page | |||
}); | }); | ||
Line 124: | Line 136: | ||
} | } | ||
}; | }; | ||
// Listen for resize events | // Listen for resize events | ||
$(window).on('resize', resizeHandler); | $(window).on('resize', resizeHandler); | ||
Line 131: | Line 143: | ||
}); | }); | ||
// Bind | // Initially hide elements with the "highlight-phrase" class | ||
$('.lightbox-button').on('click', function() { | document.querySelectorAll(".highlight-phrase").forEach(function (element) { | ||
element.style.display = "none"; // Hide elements initially | |||
}); | |||
// Bind lightbox functionality | |||
$('.lightbox-button').on('click', function () { | |||
// Get the target <div> ID from the button's data-target attribute | // Get the target <div> ID from the button's data-target attribute | ||
var targetDivId = $(this).data('target'); // e.g., '#verse-1' | var targetDivId = $(this).data('target'); // e.g., '#verse-1' | ||
Line 139: | Line 158: | ||
if (associatedSvg.length > 0) { | if (associatedSvg.length > 0) { | ||
openLightbox(associatedSvg[0]); | openLightbox(associatedSvg[0]); | ||
} | } | ||
}); | }); | ||
// | // Open the lightbox and display the SVG in full-screen | ||
function openLightbox(svgElement) { | function openLightbox(svgElement) { | ||
// Create lightbox container if it doesn't exist | // Create lightbox container if it doesn't exist | ||
var lightbox = $('<div id="lightbox-overlay" class="lightbox-overlay">') | var lightbox = $('<div id="lightbox-overlay" class="lightbox-overlay">') | ||
.appendTo('body') | .appendTo('body') | ||
Line 162: | Line 181: | ||
// Create the SVG container in the lightbox | // Create the SVG container in the lightbox | ||
var lightboxSvgContainer = $('<div class="lightbox-svg-container">') | |||
.appendTo(lightbox) | .appendTo(lightbox) | ||
.css({ | .css({ | ||
Line 171: | Line 190: | ||
}); | }); | ||
var lightboxSvg = $(svgElement).clone().appendTo(lightboxSvgContainer); // Clone the SVG | var lightboxSvg = $(svgElement).clone().appendTo(lightboxSvgContainer); // Clone the SVG | ||
// resize the svg to the available space | |||
lightboxSvg.css({ | lightboxSvg.css({ | ||
'width': '100%', | 'width': '100%', | ||
Line 192: | Line 211: | ||
}); | }); | ||
var closeButton = $('<button class="lightbox-close-button">Close</button>') | var closeButton = $('<button class="lightbox-close-button">Close</button>') | ||
.appendTo(lightbox) | .appendTo(lightbox) | ||
Line 207: | Line 225: | ||
zIndex: 10000 | zIndex: 10000 | ||
}) | }) | ||
.on('click', function() { | .on('click', function () { | ||
// Close the lightbox when the close button is clicked | |||
lightbox.remove(); | lightbox.remove(); | ||
}); | }); | ||
lightbox.on('click', function (event) { | |||
lightbox.on('click', function(event) { | // Close the lightbox when clicking outside the SVG | ||
if ($(event.target).is(lightbox)) { | if ($(event.target).is(lightbox)) { | ||
lightbox.remove(); | lightbox.remove(); | ||
} | } | ||
}); | }); | ||
// Close the lightbox | // Close the lightbox with the Escape key | ||
$(document).on('keydown', function(event) { | $(document).on('keydown', function (event) { | ||
if (event.key === "Escape" || event.keyCode === 27) { | if (event.key === "Escape" || event.keyCode === 27) { | ||
lightbox.remove(); | lightbox.remove(); | ||
$(document).off('keydown'); // Remove the keydown listener to prevent multiple bindings | $(document).off('keydown'); // Remove the keydown listener to prevent multiple bindings | ||
Line 227: | Line 245: | ||
}); | }); | ||
} | } | ||
}); | |||
} | |||
}); | }); |
Revision as of 17:37, 17 January 2025
/* Any JavaScript here will be loaded for all users on every page load. */ // Function to check if all <pre class="mermaid"> elements are processed function checkMermaidProcessed() { var mermaidPreElements = document.querySelectorAll('pre.mermaid'); var allProcessed = true; mermaidPreElements.forEach(function (element) { if (!element.hasAttribute('data-processed') || element.getAttribute('data-processed') !== 'true') { allProcessed = false; } }); return allProcessed; } // Function to wait until all Mermaid diagrams are processed function waitForMermaidProcessing(callback) { var interval = setInterval(function () { if (checkMermaidProcessed()) { clearInterval(interval); callback(); // Once all elements are processed, run the callback } }, 100); // Check every 100ms } function toggleVisibility(containerId, className) { //console.log("Toggling visibility for " + className + " in " + containerId); var container = document.getElementById(containerId); if (container) { var elements = container.querySelectorAll("g." + className); for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (element.style.display === "none") { element.style.display = ""; // Show element } else { element.style.display = "none"; // Hide element } } } else { console.warn("Container with ID \"" + containerId + "\" not found."); } } function attachToggleListeners() { //console.log("Attaching event listeners to toggle links."); var toggleLinks = document.querySelectorAll("[data-container-id][data-class]"); //console.log("Found " + toggleLinks.length + " links."); // If no toggle links are found, print a warning if (toggleLinks.length === 0) { console.warn("No toggle links found on the page."); } for (var i = 0; i < toggleLinks.length; i++) { (function (toggleLink) { toggleLink.addEventListener("click", function (event) { event.preventDefault(); // Prevent default link behavior var containerId = toggleLink.getAttribute("data-container-id"); var className = toggleLink.getAttribute("data-class"); toggleVisibility(containerId, className); }); })(toggleLinks[i]); } } // =========================== $(document).ready(function () { //console.log("Document ready. Attaching event listeners to toggle links."); // Now attach event listeners for toggling visibility attachToggleListeners(); // Wait until all Mermaid diagrams are processed waitForMermaidProcessing(function () { //console.log("Mermaid diagrams are fully processed."); $('div[id^="verse-"]').each(function () { var parentDiv = $(this); var svg = parentDiv.find('svg'); var panZoomInstance; if (svg.length > 0) { var preElement = parentDiv.find('pre.mermaid'); // The <pre> element containing the SVG var preWidth = preElement.width(); var preHeight = preElement.height(); var viewBox = svg[0].getAttribute('viewBox'); if (viewBox) { var viewBoxValues = viewBox.split(' '); var viewBoxWidth = parseFloat(viewBoxValues[2]); var viewBoxHeight = parseFloat(viewBoxValues[3]); var scaleX = preWidth / viewBoxWidth; var scaleY = preHeight / viewBoxHeight; var scale = Math.min(scaleX, scaleY); svg.css({ 'width': (preWidth) + 'px', 'max-width': (preWidth) + 'px', 'height': (viewBoxHeight * scale) + 'px', 'position': 'relative' // Ensure the SVG has a positioning context }); panZoomInstance = svgPanZoom(svg[0], { panEnabled: true, controlIconsEnabled: false, zoomEnabled: true, dblClickZoomEnabled: true, contain: true, fit: true, center: false }); // Resize handler to keep SVG scaled on window resize var resizeHandler = function () { var newWidth = preElement.width(); var newHeight = preElement.height(); //console.log('pre.mermaid container resized to: ', newWidth, newHeight); var newScaleX = newWidth / viewBoxWidth; var newScaleY = newHeight / viewBoxHeight; var newScale = Math.min(newScaleX, newScaleY); svg.css({ 'width': (newWidth) + 'px', 'max-width': (newWidth) + 'px' //'height': (viewBoxHeight * newScale) + 'px' // Do not change the height to avoid reflowing the html page }); if (panZoomInstance) { panZoomInstance.resize(); } }; // Listen for resize events $(window).on('resize', resizeHandler); } } }); // Initially hide elements with the "highlight-phrase" class document.querySelectorAll(".highlight-phrase").forEach(function (element) { element.style.display = "none"; // Hide elements initially }); // Bind lightbox functionality $('.lightbox-button').on('click', function () { // Get the target <div> ID from the button's data-target attribute var targetDivId = $(this).data('target'); // e.g., '#verse-1' var parentDiv = $(targetDivId); // Find the corresponding <div> by ID var associatedSvg = parentDiv.find('svg'); // Find the SVG inside the <pre> if (associatedSvg.length > 0) { openLightbox(associatedSvg[0]); } }); // Open the lightbox and display the SVG in full-screen function openLightbox(svgElement) { // Create lightbox container if it doesn't exist var lightbox = $('<div id="lightbox-overlay" class="lightbox-overlay">') .appendTo('body') .css({ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', backgroundColor: 'rgba(128, 128, 128, 0.8)', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 9999, }); // Create the SVG container in the lightbox var lightboxSvgContainer = $('<div class="lightbox-svg-container">') .appendTo(lightbox) .css({ width: '95%', height: '95%', overflow: 'hidden', backgroundColor: 'rgba(255, 255, 255, 1.0)', }); var lightboxSvg = $(svgElement).clone().appendTo(lightboxSvgContainer); // Clone the SVG // resize the svg to the available space lightboxSvg.css({ 'width': '100%', 'max-width': '100%', 'height': '100%' }); // Apply svg-pan-zoom to the cloned SVG in the lightbox var panZoomInstanceLightbox = svgPanZoom(lightboxSvg[0], { panEnabled: true, controlIconsEnabled: false, zoomEnabled: true, dblClickZoomEnabled: true, contain: true, fit: true, center: true }); var closeButton = $('<button class="lightbox-close-button">Close</button>') .appendTo(lightbox) .css({ position: 'absolute', top: '10px', right: '10px', backgroundColor: '#fff', color: '#000', border: '1px solid #bbb', borderRadius: '1rem', padding: '10px 20px', cursor: 'pointer', zIndex: 10000 }) .on('click', function () { // Close the lightbox when the close button is clicked lightbox.remove(); }); lightbox.on('click', function (event) { // Close the lightbox when clicking outside the SVG if ($(event.target).is(lightbox)) { lightbox.remove(); } }); // Close the lightbox with the Escape key $(document).on('keydown', function (event) { if (event.key === "Escape" || event.keyCode === 27) { lightbox.remove(); $(document).off('keydown'); // Remove the keydown listener to prevent multiple bindings } }); } }); });