4,554
edits
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
Line 1,669: | Line 1,669: | ||
/* ---------- /Softwear PRINT ---------- */ | /* ---------- /Softwear PRINT ---------- */ | ||
// | /* === SW PRINT: native fallback for Entry pages === */ | ||
(function () { | |||
// guard so we don’t double-bind if this block is included twice | |||
if (window.__swPrintNativeBound) return; | |||
window.__swPrintNativeBound = true; | |||
// util: create/toggle the chooser safely (no jQuery required) | |||
function ensurePrintChooserNative() { | |||
var chooser = document.getElementById("print-chooser"); | |||
if (!chooser) { | |||
chooser = document.createElement("div"); | |||
chooser.id = "print-chooser"; | |||
chooser.className = "print-chooser"; | |||
chooser.style.display = "none"; | |||
chooser.innerHTML = | |||
'<a href="#" id="print-with-border" class="print-choice">border</a> ' + | |||
'<a href="#" id="print-no-border" class="print-choice">no border</a>'; | |||
var printBtn = document.getElementById("print-button"); | |||
if (printBtn && printBtn.parentNode) { | |||
printBtn.parentNode.insertBefore(chooser, printBtn.nextSibling); | |||
} | |||
} | |||
return chooser; | |||
} | |||
function toggleChooser(show) { | |||
var chooser = ensurePrintChooserNative(); | |||
var want = | |||
typeof show === "boolean" ? show : chooser.style.display === "none"; | |||
chooser.style.display = want ? "block" : "none"; | |||
var article = document.getElementById("show-article"); | |||
if (article) { | |||
if (want) article.classList.add("print-opts-open"); | |||
else article.classList.remove("print-opts-open"); | |||
} | |||
console.log("[swprint-native] chooser", want ? "shown" : "hidden"); | |||
} | |||
console.log("[swprint] | |||
} | } | ||
// | // MAIN: start print with pref | ||
function | function swStartPrint(borderPref) { | ||
console.log("[swprint-native] start with pref:", borderPref); | |||
try { | |||
preloadFontForPrint && preloadFontForPrint(); | |||
} catch (e) {} | |||
// 1) Prefer local .print-only (Entry page) | |||
var local = document.querySelector(".print-only"); | |||
if (local) { | |||
console.log("[swprint-native] using local .print-only"); | |||
console.log("[swprint] | toggleChooser(false); | ||
return buildIframeAndPrint(local.outerHTML, borderPref); | |||
} | |||
} | |||
// 2) Otherwise fetch by title (modal / other pages) | |||
var title = | |||
window.currentEntryTitle || | |||
(window.mw && | |||
mw.config && | |||
typeof mw.config.get === "function" && | |||
mw.config.get("wgPageName")); | |||
if ( | |||
!title || | |||
!(window.mw && mw.util && typeof mw.util.getUrl === "function") | |||
) { | |||
console.warn( | |||
"[swprint-native] no title/mw.util; falling back to window.print()" | |||
); | |||
return window.print(); | |||
} | } | ||
var url = mw.util.getUrl(title); | |||
try { | |||
url = typeof cacheBust === "function" ? cacheBust(url) : url; | |||
} catch (e) {} | |||
console.log("[swprint-native] fetching:", url); | |||
fetch(url, { credentials: "same-origin" }) | |||
.then(function (r) { | |||
return r.text(); | |||
}) | |||
.then(function (html) { | |||
var tmp = document.createElement("div"); | |||
tmp.innerHTML = html; | |||
var printOnly = tmp.querySelector(".print-only"); | |||
if (!printOnly) { | |||
console.warn( | console.warn( | ||
"[swprint] | "[swprint-native] no .print-only in fetched page; window.print()" | ||
); | ); | ||
return window.print(); | |||
} | } | ||
} else { | toggleChooser(false); | ||
buildIframeAndPrint(printOnly.outerHTML, borderPref); | |||
}) | |||
.catch(function (err) { | |||
console.warn("[swprint-native] fetch failed; window.print()", err); | |||
window.print(); | |||
}); | |||
} | |||
// helper: build iframe and call print (mirrors your jQuery version) | |||
function buildIframeAndPrint(printHtml, borderPref) { | |||
console.log("[swprint-native] buildIframeAndPrint()"); | |||
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(); | |||
var base = doc.createElement("base"); | |||
base.href = location.origin + "/"; | |||
doc.head.appendChild(base); | |||
var cssUrl = | |||
"/index.php?title=MediaWiki:Print.css&action=raw&ctype=text/css"; | |||
try { | |||
cssUrl = typeof cacheBust === "function" ? cacheBust(cssUrl) : cssUrl; | |||
} catch (e) {} | |||
var linkCss = doc.createElement("link"); | |||
linkCss.rel = "stylesheet"; | |||
linkCss.href = cssUrl; | |||
var cssLoaded = new Promise(function (res) { | |||
linkCss.onload = function () { | |||
console.log("[swprint-native] print CSS loaded"); | |||
res(); | |||
}; | |||
linkCss.onerror = function () { | |||
console.warn("[swprint-native] print CSS failed"); | |||
res(); | |||
}; | |||
}); | |||
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); | |||
doc.body.innerHTML = printHtml; | |||
// border pref class on <html> | |||
var root = doc.documentElement; | |||
if (borderPref === "without") root.classList.add("print-no-border"); | |||
else root.classList.remove("print-no-border"); | |||
console.log("[swprint-native] borderPref applied:", borderPref); | |||
// small inline tweaks (same as your version) | |||
var style = doc.createElement("style"); | |||
style.textContent = | |||
"@media print{.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}.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}[class^='article-label-']{margin-top:0!important}.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}.article-title-link{margin:0!important;padding:0!important}.article-title-link>*{margin:0!important}.link-pdf{margin-top:0!important}#article-content>:last-child{padding-bottom:0!important}#article-content>:last-child::after{content:none!important}}"; | |||
doc.head.appendChild(style); | |||
var styleFix = doc.createElement("style"); | |||
styleFix.textContent = | |||
"@media print {.article-external-reference a,.link-pdf a{white-space:nowrap!important;word-break:normal!important;overflow-wrap:normal!important;text-decoration:underline}.article-external-reference{overflow-wrap:anywhere;word-break:break-word}a[href]{position:relative}}"; | |||
doc.head.appendChild(styleFix); | |||
// wait helpers (minimal) | |||
function nextFrame() { | |||
return new Promise(function (r) { | |||
(iframe.contentWindow.requestAnimationFrame || setTimeout)(r, 0); | |||
}); | |||
} | |||
var waitFonts = | |||
doc.fonts && doc.fonts.ready | |||
? Promise.race([ | |||
doc.fonts.ready, | |||
new Promise((r) => setTimeout(r, 1200)), | |||
]) | |||
: Promise.resolve(); | |||
Promise.all([cssLoaded, waitFonts, nextFrame()]).then(function () { | |||
console.log("[swprint-native] resources ready; print()"); | |||
// filename by title | |||
var numEl = doc.querySelector(".article-entry-number"); | |||
var entryNum = ""; | |||
if (numEl) { | |||
var m = (numEl.textContent || "").match(/\d+/); | |||
entryNum = m ? m[0] : ""; | |||
} | } | ||
} | var desiredTitle = | ||
(entryNum ? entryNum + "." : "") + "softwear.directory"; | |||
var oldIframeTitle = doc.title; | |||
var oldParentTitle = document.title; | |||
iframe.contentWindow.onafterprint = function () { | |||
try { | |||
doc.title = oldIframeTitle; | |||
document.title = oldParentTitle; | |||
} catch (e) {} | |||
setTimeout(function () { | |||
if (iframe.parentNode) iframe.parentNode.removeChild(iframe); | |||
}, 100); | |||
console.log("[swprint-native] afterprint cleanup"); | |||
}; | |||
doc.title = desiredTitle; | |||
document.title = desiredTitle; | |||
iframe.contentWindow.focus(); | |||
iframe.contentWindow.print(); | |||
setTimeout(function () { | |||
try { | |||
doc.title = oldIframeTitle; | |||
document.title = oldParentTitle; | |||
} catch (e) {} | |||
if (iframe.parentNode) iframe.parentNode.removeChild(iframe); | |||
console.log("[swprint-native] timeout cleanup"); | |||
}, 1200); | |||
}); | |||
} | |||
// Bind native click to PRINT button (toggle choices) | |||
var printBtn = document.getElementById("print-button"); | |||
if (printBtn) { | |||
printBtn.addEventListener( | |||
"click", | |||
function (e) { | |||
e.preventDefault(); | |||
console.log("[swprint-native] print-button clicked"); | |||
toggleChooser(); | |||
}, | |||
false | |||
); | |||
} | } | ||
// Bind native clicks to choices (border/no-border) | |||
function onChoice(e) { | |||
var a = e.target.closest && e.target.closest("a"); | |||
var | if (!a) return; | ||
if (! | if (a.id !== "print-with-border" && a.id !== "print-no-border") return; | ||
e.preventDefault(); | |||
var pref = a.id === "print-no-border" ? "without" : "with"; | |||
console.log("[swprint-native] choice clicked:", pref); | |||
swStartPrint(pref); | |||
} | } | ||
// | // if already present | ||
["print-with-border", "print-no-border"].forEach(function (id) { | ["print-with-border", "print-no-border"].forEach(function (id) { | ||
var el = document.getElementById(id); | var el = document.getElementById(id); | ||
if (el) | if (el) el.addEventListener("click", onChoice, false); | ||
}); | }); | ||
// and delegate for dynamically created chooser | |||
document.addEventListener("click", onChoice, false); | |||
// | console.log("[swprint-native] fallback bound"); | ||
})(); | |||
//ENDEND | |||
// Close modal with Close button | |||
$("#close-button").on("click", function () { | |||
$("#print-chooser").hide(); | |||
$("#show-article").removeClass("print-opts-open"); | |||
$(".list-container").removeClass("fade-out"); | |||
closeModal(); | |||
}); | |||
} | |||
// Close modal and remove fade out also when clicking outside of card | // Close modal and remove fade out also when clicking outside of card | ||
$(document).on("mousedown", function (event) { | $(document).on("mousedown", function (event) { |