/* global window, document */ (function () { "use strict"; var Luxtools = window.Luxtools || (window.Luxtools = {}); var Lightbox = Luxtools.Lightbox; var OpenService = Luxtools.OpenService; var GalleryThumbnails = Luxtools.GalleryThumbnails; var Scratchpads = Luxtools.Scratchpads; var CalendarWidget = Luxtools.CalendarWidget; // ============================================================ // Click Handlers // ============================================================ function findOpenElement(target) { var el = target; while (el && el !== document) { if (el.classList && el.classList.contains("luxtools-open")) return el; el = el.parentNode; } return null; } function findGalleryItem(target) { var el = target; while (el && el !== document) { if (el.classList && el.classList.contains("luxtools-gallery-item")) return el; el = el.parentNode; } return null; } function onClick(event) { // Image gallery lightbox: intercept clicks so we don't navigate away. var galleryItem = findGalleryItem(event.target); if (galleryItem && Lightbox && Lightbox.open) { var gallery = galleryItem.closest ? galleryItem.closest('div.luxtools-gallery[data-luxtools-gallery="1"]') : null; if (gallery) { event.preventDefault(); Lightbox.open(gallery, galleryItem); return; } } var el = findOpenElement(event.target); if (!el) return; // {{open>...}} renders as a link; avoid jumping to '#'. if (el.tagName && el.tagName.toLowerCase() === "a") { event.preventDefault(); } var raw = el.getAttribute("data-path") || ""; if (!raw) return; if (!OpenService || !OpenService.openViaService) return; // Prefer local client service. OpenService.openViaService(el, raw).catch(function (err) { // If the browser blocks the request before it reaches localhost (mixed-content, // extensions, stricter CORS handling), fall back to a no-CORS GET ping. if (OpenService && OpenService.pingOpenViaImage) { OpenService.pingOpenViaImage(el, raw); } // Fallback to old behavior (often blocked in modern browsers). var url = OpenService && OpenService.normalizeToFileUrl ? OpenService.normalizeToFileUrl(raw) : ""; if (!url) return; console.warn( "Local client service failed, falling back to file:// navigation:", err, ); try { window.open(url, "_blank", "noopener"); } catch (e) { try { window.location.href = url; } catch (e2) { console.error("Failed to open file URL:", e2); } } }); } function initChronologicalEventTimes() { var nodes = document.querySelectorAll( ".luxtools-event-time[data-luxtools-start]", ); if (!nodes || nodes.length === 0) return; var formatter; try { formatter = new Intl.DateTimeFormat("de-DE", { hour: "2-digit", minute: "2-digit", hour12: false, }); } catch (e) { formatter = null; } for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var raw = node.getAttribute("data-luxtools-start") || ""; if (!raw) continue; var date = new Date(raw); if (isNaN(date.getTime())) continue; var label; if (formatter) { label = formatter.format(date); } else { var hh = String(date.getHours()).padStart(2, "0"); var mm = String(date.getMinutes()).padStart(2, "0"); label = hh + ":" + mm; } node.textContent = label; } } // ============================================================ // Purge Cache Dialog // ============================================================ function initPurgeCacheDialog() { document.addEventListener( "click", function (e) { var link = e.target.closest ? e.target.closest("a.luxtools-invalidate-cache") : null; if (!link) return; e.preventDefault(); var href = link.getAttribute("href") || ""; var lang = window.LANG && window.LANG.plugins && window.LANG.plugins.luxtools ? window.LANG.plugins.luxtools : {}; var html = '
'; html += ''; html += '

' + (lang.cache_purge_dialog_title || "Purge Cache") + "

"; html += "

" + (lang.cache_purge_dialog_intro || "The DokuWiki cache will always be purged. Optionally also purge the luxtools-specific caches:") + "

"; html += '

"; html += '

"; html += '
'; html += ' "; html += '"; html += "
"; html += "
"; Luxtools.Dialog.show(html); var container = Luxtools.Dialog.getContainer(); var cancelBtn = container.querySelector(".luxtools-purge-cancel"); if (cancelBtn) { cancelBtn.addEventListener("click", function () { Luxtools.Dialog.close(); }); } var confirmBtn = container.querySelector(".luxtools-purge-confirm"); if (confirmBtn) { confirmBtn.addEventListener("click", function () { var url = href; var plCheck = container.querySelector("#luxtools-purge-pagelinks"); var thCheck = container.querySelector("#luxtools-purge-thumbs"); if (plCheck && plCheck.checked) { url += "&luxtools_purge_pagelinks=1"; } if (thCheck && thCheck.checked) { url += "&luxtools_purge_thumbs=1"; } Luxtools.Dialog.close(); window.location.href = url; }); } }, false, ); } // ============================================================ // Calendar Sync Button (syntax widget) // ============================================================ function initCalendarSyncButtons() { document.addEventListener( "click", function (e) { var btn = e.target; if ( !btn || !btn.classList || !btn.classList.contains("luxtools-calendar-sync-btn") ) return; e.preventDefault(); var ajaxUrl = btn.getAttribute("data-luxtools-ajax-url") || ""; var sectok = btn.getAttribute("data-luxtools-sectok") || ""; if (!ajaxUrl) return; var status = btn.parentNode ? btn.parentNode.querySelector(".luxtools-calendar-sync-status") : null; btn.disabled = true; if (status) { status.textContent = "Syncing..."; status.style.color = ""; } var xhr = new XMLHttpRequest(); xhr.open("POST", ajaxUrl, true); xhr.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded", ); xhr.onload = function () { btn.disabled = false; try { var r = JSON.parse(xhr.responseText); if (status) { status.textContent = r.message || (r.ok ? "Done" : "Failed"); status.style.color = r.ok ? "green" : "red"; } } catch (ex) { if (status) { status.textContent = "Error"; status.style.color = "red"; } } }; xhr.onerror = function () { btn.disabled = false; if (status) { status.textContent = "Network error"; status.style.color = "red"; } }; xhr.send( "call=luxtools_calendar_sync§ok=" + encodeURIComponent(sectok), ); }, false, ); } // ============================================================ // Initialize // ============================================================ document.addEventListener("click", onClick, false); document.addEventListener( "DOMContentLoaded", function () { if (GalleryThumbnails && GalleryThumbnails.init) GalleryThumbnails.init(); initChronologicalEventTimes(); if (CalendarWidget && CalendarWidget.init) CalendarWidget.init(); initPurgeCacheDialog(); initCalendarSyncButtons(); }, false, ); document.addEventListener( "DOMContentLoaded", function () { if (Scratchpads && Scratchpads.init) Scratchpads.init(); }, false, ); Luxtools.initChronologicalEventTimes = initChronologicalEventTimes; })();