295 lines
9.1 KiB
JavaScript
295 lines
9.1 KiB
JavaScript
/* 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;
|
|
|
|
for (var i = 0; i < nodes.length; i++) {
|
|
var node = nodes[i];
|
|
var raw = node.getAttribute("data-luxtools-start") || "";
|
|
if (!raw) continue;
|
|
|
|
var match = raw.match(/T(\d{2}):(\d{2})/);
|
|
if (!match) continue;
|
|
|
|
node.textContent = match[1] + ":" + match[2];
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// 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 = '<div class="luxtools-dialog-content">';
|
|
html +=
|
|
'<button type="button" class="luxtools-dialog-close" aria-label="Close">×</button>';
|
|
html +=
|
|
'<h3 class="luxtools-dialog-title">' +
|
|
(lang.cache_purge_dialog_title || "Purge Cache") +
|
|
"</h3>";
|
|
html +=
|
|
"<p>" +
|
|
(lang.cache_purge_dialog_intro ||
|
|
"The DokuWiki cache will always be purged. Optionally also purge the luxtools-specific caches:") +
|
|
"</p>";
|
|
html +=
|
|
'<p><label><input type="checkbox" id="luxtools-purge-pagelinks"> <strong>' +
|
|
(lang.cache_purge_pagelinks_label || "Pagelinks") +
|
|
"</strong>";
|
|
html +=
|
|
" – " +
|
|
(lang.cache_purge_pagelinks_desc ||
|
|
"Purges the pagelink mapping cache") +
|
|
"</label></p>";
|
|
html +=
|
|
'<p><label><input type="checkbox" id="luxtools-purge-thumbs"> <strong>' +
|
|
(lang.cache_purge_thumbs_label || "Thumbnails") +
|
|
"</strong>";
|
|
html +=
|
|
" – " +
|
|
(lang.cache_purge_thumbs_desc ||
|
|
"Purges all cached image thumbnails") +
|
|
"</label></p>";
|
|
html += '<div class="luxtools-dialog-actions">';
|
|
html +=
|
|
'<button type="button" class="button luxtools-purge-confirm">' +
|
|
(lang.cache_purge_confirm || "Purge Cache") +
|
|
"</button> ";
|
|
html +=
|
|
'<button type="button" class="button luxtools-purge-cancel">' +
|
|
(lang.cache_purge_cancel || "Cancel") +
|
|
"</button>";
|
|
html += "</div>";
|
|
html += "</div>";
|
|
|
|
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;
|
|
})();
|