4,554
edits
No edit summary |
No edit summary |
||
Line 1,297: | Line 1,297: | ||
$(document).off( | $(document).off( | ||
"click.print", | "click.print", | ||
"#print-button, #print-with-border, #print-no-border" | "#print-button, #print-with-border, #print-no-border, #print-chooser a.print-choice, #print-options a#print-with-border, #print-options a#print-no-border" | ||
); | ); | ||
// One handler for all | // One handler for all the print UI | ||
$(document).on( | $(document).on( | ||
"click.print", | "click.print", | ||
"#print-button, #print-with-border, #print-no-border", | "#print-button, #print-with-border, #print-no-border, #print-chooser a.print-choice, #print-options a#print-with-border, #print-options a#print-no-border", | ||
function (e) { | function (e) { | ||
e.preventDefault(); | // Normalize the target to the closest <a> (covers the widget’s <a><button></button></a>) | ||
var $anchor = $(e.target).closest("a"); | |||
if ($anchor.length) e.preventDefault(); | |||
var id = | var rawId = this.id; // in case you clicked the element with the id directly | ||
var id = ($anchor.attr("id") || rawId || "").trim(); | |||
// | console.log("[print] click:", { | ||
target: e.target.tagName, | |||
thisId: rawId, | |||
anchorId: id, | |||
}); | |||
// Toggle chooser if main [print] clicked | |||
if (id === "print-button") { | if (id === "print-button") { | ||
var $chooser = ensurePrintChooser(); | var $chooser = ensurePrintChooser(); | ||
$chooser.toggle(); | $chooser.toggle(); | ||
var $article = $("#show-article"); | var $article = $("#show-article"); | ||
if ($chooser.is(":visible")) { | if ($chooser.is(":visible")) { | ||
Line 1,321: | Line 1,329: | ||
$article.removeClass("print-opts-open"); | $article.removeClass("print-opts-open"); | ||
} | } | ||
return; // | |||
console.log( | |||
"[print] toggled chooser; visible=", | |||
$chooser.is(":visible") | |||
); | |||
return; // don't start printing yet | |||
} | |||
// From here on it must be one of the two options | |||
if (id !== "print-with-border" && id !== "print-no-border") { | |||
console.warn("[print] unexpected click (ignoring). id=", id); | |||
return; | |||
} | } | ||
var $btn = $anchor.length ? $anchor : $(this); | |||
var $btn = $(this); | if ($btn.data("busy")) { | ||
if ($btn.data("busy")) return; | console.log("[print] busy, ignoring click"); | ||
return; | |||
} | |||
$btn.data("busy", true); | $btn.data("busy", true); | ||
var borderPref = id === "print-no-border" ? "without" : "with"; | var borderPref = id === "print-no-border" ? "without" : "with"; | ||
console.log("[print] option chosen:", borderPref); | console.log("[print] option chosen:", borderPref); | ||
Line 1,335: | Line 1,355: | ||
preloadFontForPrint(); | preloadFontForPrint(); | ||
// | // Prefer local .print-only (Entry page) | ||
var localPrintOnly = $(".print-only").first(); | var localPrintOnly = $(".print-only").first(); | ||
console.log("[print] local .print-only present:", localPrintOnly.length); | console.log("[print] local .print-only present:", localPrintOnly.length); | ||
Line 1,341: | Line 1,361: | ||
if (localPrintOnly.length) { | if (localPrintOnly.length) { | ||
console.log("[print] using local .print-only on this page"); | console.log("[print] using local .print-only on this page"); | ||
$("#print-chooser").hide(); | $("#print-chooser").hide(); | ||
$("#show-article").removeClass("print-opts-open"); | $("#show-article").removeClass("print-opts-open"); | ||
buildIframeAndPrint(localPrintOnly.prop("outerHTML")); | buildIframeAndPrint(localPrintOnly.prop("outerHTML")); | ||
return; | return; | ||
} | } | ||
// | // Otherwise fetch by title (modal/home list flow) | ||
var title = | var title = | ||
window.currentEntryTitle || | window.currentEntryTitle || | ||
Line 1,355: | Line 1,374: | ||
if (!title) { | if (!title) { | ||
console.warn( | console.warn("[print] no title; falling back to window.print()"); | ||
window.print(); | window.print(); | ||
$btn.data("busy", false); | $btn.data("busy", false); | ||
Line 1,371: | Line 1,388: | ||
var $tmp = $("<div>").html(html); | var $tmp = $("<div>").html(html); | ||
var $print = $tmp.find(".print-only").first(); | var $print = $tmp.find(".print-only").first(); | ||
console.log( | console.log("[print] .print-only in fetched page:", $print.length); | ||
if (!$print.length) { | if (!$print.length) { | ||
console.warn("[print] no .print-only | console.warn( | ||
"[print] no .print-only in fetched page; window.print()" | |||
); | |||
window.print(); | window.print(); | ||
$btn.data("busy", false); | $btn.data("busy", false); | ||
Line 1,395: | Line 1,411: | ||
}); | }); | ||
// | // Helper scoped here so it can see borderPref and $btn | ||
function buildIframeAndPrint(printHtml) { | function buildIframeAndPrint(printHtml) { | ||
console.log("[print] buildIframeAndPrint: starting"); | |||
// Build hidden iframe | // Build hidden iframe | ||
var iframe = document.createElement("iframe"); | var iframe = document.createElement("iframe"); | ||
Line 1,430: | Line 1,447: | ||
var cssLoaded = new Promise(function (resolve) { | var cssLoaded = new Promise(function (resolve) { | ||
linkCss.onload = function () { | linkCss.onload = function () { | ||
console.log("[print] print CSS loaded"); | |||
resolve(); | resolve(); | ||
}; | }; | ||
Line 1,438: | Line 1,456: | ||
}); | }); | ||
// Preload the font *inside* iframe | // Preload the font *inside* iframe | ||
var linkFont = doc.createElement("link"); | var linkFont = doc.createElement("link"); | ||
linkFont.rel = "preload"; | linkFont.rel = "preload"; | ||
Line 1,451: | Line 1,469: | ||
// Inject the printable HTML | // Inject the printable HTML | ||
doc.body.innerHTML = printHtml; | doc.body.innerHTML = printHtml; | ||
console.log("[print] injected print HTML"); | |||
// Apply border preference (class on <html>) | // Apply border preference (class on <html>) | ||
Line 1,456: | Line 1,475: | ||
var rootHtml = doc.documentElement; | var rootHtml = doc.documentElement; | ||
if (borderPref === "without") { | if (borderPref === "without") { | ||
rootHtml.classList | |||
? rootHtml.classList.add("print-no-border") | |||
: (rootHtml.className += " print-no-border"); | |||
} else { | } else { | ||
rootHtml.classList | |||
rootHtml.classList.remove("print-no-border") | ? rootHtml.classList.remove("print-no-border") | ||
: (rootHtml.className = rootHtml.className.replace( | |||
rootHtml.className = rootHtml.className.replace( | /\bprint-no-border\b/g, | ||
"" | |||
)); | |||
} | } | ||
console.log("[print] borderPref applied:", borderPref); | |||
})(); | })(); | ||
// | // Clean empty paragraphs | ||
(function () { | (function () { | ||
var ps = doc.querySelectorAll("#article-content p"); | var ps = doc.querySelectorAll("#article-content p"); | ||
Line 1,495: | Line 1,514: | ||
})(); | })(); | ||
// Inline | // Inline tweaks | ||
(function () { | (function () { | ||
var css = | var css = | ||
Line 1,513: | Line 1,532: | ||
' .article-quote + [class^="article-label-"],' + | ' .article-quote + [class^="article-label-"],' + | ||
' .article-mod-line + [class^="article-label-"]{margin-top:0.9mm!important;}' + | ' .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;padding:0!important;}" + | ||
" .article-title-link > *{margin:0!important;}" + | " .article-title-link > *{margin:0!important;}" + | ||
Line 1,531: | Line 1,545: | ||
// PDF-friendly links | // PDF-friendly links | ||
var linkCssFix | var linkCssFix = | ||
"@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}}"; | |||
"@media print { | var styleFix = doc.createElement("style"); | ||
styleFix.textContent = linkCssFix; | |||
doc.head.appendChild(styleFix); | |||
doc.head.appendChild( | |||
(function () { | (function () { | ||
Line 1,561: | Line 1,571: | ||
} | } | ||
} | } | ||
a.style.whiteSpace = "nowrap"; | a.style.whiteSpace = "nowrap"; | ||
a.style.wordBreak = "normal"; | a.style.wordBreak = "normal"; | ||
Line 1,623: | Line 1,628: | ||
waitSpecificFont(1200), | waitSpecificFont(1200), | ||
nextFrame(), | nextFrame(), | ||
]).then(function () { | ]) | ||
.then(function () { | |||
console.log("[print] resources ready; calling print()"); | |||
try { | |||
// Filename via document.title | |||
var entryNum = ""; | |||
var numEl = doc.querySelector(".article-entry-number"); | |||
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); | |||
$btn.data("busy", false); | |||
console.log("[print] afterprint cleanup done"); | |||
}; | |||
doc.title = desiredTitle; | |||
document.title = desiredTitle; | |||
iframe.contentWindow.focus(); | |||
iframe.contentWindow.print(); | |||
// Safety cleanup if onafterprint never fires | |||
setTimeout(function () { | |||
try { | |||
doc.title = oldIframeTitle; | |||
document.title = oldParentTitle; | |||
} catch (e) {} | |||
if (iframe.parentNode) iframe.parentNode.removeChild(iframe); | |||
$btn.data("busy", false); | |||
console.log("[print] timeout cleanup done"); | |||
}, 1000); | |||
} catch (err) { | |||
console.warn("[print] failed before print:", err); | |||
$btn.data("busy", false); | $btn.data("busy", false); | ||
} | } | ||
}) | |||
console.warn("[print] | .catch(function (err) { | ||
console.warn("[print] Promise chain error:", err); | |||
$btn.data("busy", false); | $btn.data("busy", false); | ||
}); | |||
} | } | ||
} | } |