4,656
edits
No edit summary |
No edit summary |
||
| (41 intermediate revisions by the same user not shown) | |||
| Line 568: | Line 568: | ||
var filterType = $(this).closest(".filter").data("filter"); | var filterType = $(this).closest(".filter").data("filter"); | ||
var cardSelector = $(".card").length > 0 ? ".card" : ".community-card"; // Determine which card type is present | var cardSelector = $(".card").length > 0 ? ".card" : ".community-card"; // Determine which card type is present | ||
$("#values-" + filterType).toggle(); | $("#values-" + filterType).toggle(); | ||
| Line 584: | Line 582: | ||
processEventCards(cardSelector); | processEventCards(cardSelector); | ||
updateViews(cardSelector); | updateViews(cardSelector); | ||
}); | }); | ||
| Line 630: | Line 626: | ||
processEventCards(cardSelector); | processEventCards(cardSelector); | ||
updateViews(cardSelector); | updateViews(cardSelector); | ||
updatePrintSelectionUI(); | |||
hidePrintSelectionOptions(); | |||
console.log("Filtering process complete, updated views and borders"); | console.log("Filtering process complete, updated views and borders"); | ||
| Line 699: | Line 697: | ||
// Reset function to remove active filters | // Reset function to remove active filters | ||
$(".reset-filter").click(function (event) { | $(".reset-filter").click(function (event) { | ||
event.stopPropagation(); | event.stopPropagation(); | ||
$("#filters .values button").removeClass("active"); | $("#filters .values button").removeClass("active"); | ||
$(".open-filter").removeClass("active-filter"); | $(".open-filter").removeClass("active-filter"); | ||
$(".count-filtered-cards").text("").hide(); | $(".count-filtered-cards").text("").hide(); | ||
filterCards | filterCards(); | ||
hidePrintSelectionOptions(); | |||
}); | }); | ||
$("#filters .values button").click(function () { | $("#filters .values button").click(function () { | ||
$(this).toggleClass("active"); | $(this).toggleClass("active"); | ||
filterCards | filterCards(); | ||
}); | }); | ||
| Line 1,260: | Line 1,244: | ||
}); | }); | ||
/* ---------- Softwear PRINT ---------- */ | |||
/* ---------- Softwear PRINT | |||
/* helpers */ | /* helpers */ | ||
| Line 1,281: | Line 1,264: | ||
var $chooser = jQuery("#print-chooser"); | var $chooser = jQuery("#print-chooser"); | ||
if ($chooser.length) return $chooser; | if ($chooser.length) return $chooser; | ||
$chooser = jQuery( | $chooser = jQuery( | ||
'<div id="print-chooser" class="print-chooser" style="display:none;">' + | '<div id="print-chooser" class="print-chooser" style="display:none;">' + | ||
'<a href="#" id=" | '<a href="#" id="print-with-border" class="print-choice">show border</a> ' + | ||
'<a href="#" id=" | '<a href="#" id="print-no-border" class="print-choice">hide border</a>' + | ||
"</div>" | "</div>" | ||
); | ); | ||
jQuery("#print-button").after($chooser); | jQuery("#print-button").after($chooser); | ||
// Bind once on the chooser to catch nested elements | |||
if (!$chooser.data("swBound")) { | |||
function chooserFire(ev, where) { | |||
ev = ev || window.event; | |||
var t = ev && (ev.target || ev.srcElement); | |||
var a = t && t.closest ? t.closest("a[id]") : null; | |||
if (!a) return; | |||
var id = a.getAttribute("id"); | |||
if (id !== "print-with-border" && id !== "print-no-border") return; | |||
if (ev.preventDefault) ev.preventDefault(); | |||
if (ev.stopImmediatePropagation) ev.stopImmediatePropagation(); | |||
if (ev.stopPropagation) ev.stopPropagation(); | |||
swHandlePrintChoice(id, (window.jQuery && jQuery(a)) || null); | |||
return false; | |||
} | |||
$chooser.on("pointerdown", chooserFire); | |||
$chooser.on("touchstart", chooserFire); | |||
$chooser.on("mousedown", chooserFire); | |||
$chooser.on("click", chooserFire); | |||
$chooser.data("swBound", true); | |||
} | |||
return $chooser; | return $chooser; | ||
} | } | ||
| Line 1,296: | Line 1,302: | ||
} | } | ||
function updatePrintSelectionUI() { | |||
requestAnimationFrame(function () { | |||
var activeCount = jQuery("#filters .values button.active").length; | |||
if (activeCount > 0) { | |||
jQuery("#print-selection-wrapper").show(); | |||
} else { | |||
jQuery("#print-selection-wrapper").hide(); | |||
jQuery("#print-selection-options").hide(); | |||
} | |||
}); | |||
} | |||
function hidePrintSelectionOptions() { | |||
jQuery("#print-selection-options").hide(); | |||
} | |||
function swHandleBatchPrint(borderPref) { | |||
swPrintPreloadFont(); | |||
var $cards = jQuery(".card:visible").not(".event"); | |||
if (!$cards.length) { | |||
alert("No entries to print."); | |||
return; | |||
} | |||
var requests = []; | |||
$cards.each(function () { | |||
var $card = jQuery(this); | |||
var title = $card.data("page"); | |||
if (!title) return; | |||
var url = | |||
window.mw && mw.util && mw.util.getUrl | |||
? swPrintCacheBust(mw.util.getUrl(title)) | |||
: swPrintCacheBust("/wiki/" + String(title)); | |||
requests.push( | |||
jQuery.get(url).then(function (html) { | |||
var $tmp = jQuery("<div>").html(html); | |||
var $print = $tmp.find(".print-only").first(); | |||
return $print.length ? $print.prop("outerHTML") : ""; | |||
}) | |||
); | |||
}); | |||
Promise.all(requests) | |||
.then(function (results) { | |||
var combinedHtml = results.join(""); | |||
if (!combinedHtml.trim()) { | |||
alert("Could not generate print content."); | |||
return; | |||
} | |||
swBuildIframeAndPrint( | |||
combinedHtml, | |||
borderPref, | |||
null, | |||
"filtered.softwear.directory" | |||
); | |||
}) | |||
.catch(function () { | |||
alert("There was a problem preparing the print selection."); | |||
}); | |||
} | |||
/* small boot probe */ | |||
(function () { | (function () { | ||
try { | try { | ||
| Line 1,308: | Line 1,385: | ||
/* core: build iframe and print */ | /* core: build iframe and print */ | ||
function swBuildIframeAndPrint(printHtml, borderPref, $btn) { | function swBuildIframeAndPrint(printHtml, borderPref, $btn, filenameOverride) { | ||
// iframe | // iframe | ||
var iframe = document.createElement("iframe"); | var iframe = document.createElement("iframe"); | ||
| Line 1,343: | Line 1,416: | ||
var cssLoaded = new Promise(function (resolve) { | var cssLoaded = new Promise(function (resolve) { | ||
linkCss.onload = | linkCss.onload = resolve; | ||
linkCss.onerror = resolve; | |||
linkCss.onerror = | |||
}); | }); | ||
| Line 1,365: | Line 1,434: | ||
doc.body.innerHTML = printHtml; | doc.body.innerHTML = printHtml; | ||
// | (function () { | ||
var pres = doc.querySelectorAll(".link-pdf pre"); | |||
Array.prototype.forEach.call(pres, function (pre) { | |||
// move its children out | |||
while (pre.firstChild) { | |||
pre.parentNode.insertBefore(pre.firstChild, pre); | |||
} | |||
// remove the <pre> | |||
pre.parentNode.removeChild(pre); | |||
}); | |||
})(); | |||
// sanitize: remove inner .print-no-border if user chose WITH border | |||
(function () { | (function () { | ||
var stray = doc.querySelectorAll(".print-no-border"); | var stray = doc.querySelectorAll(".print-no-border"); | ||
if (borderPref === "with" && stray.length) { | if (borderPref === "with" && stray.length) { | ||
Array.prototype.forEach.call(stray, function (el) { | Array.prototype.forEach.call(stray, function (el) { | ||
el.className = el.className | el.className = (el.className || "") | ||
.replace(/\bprint-no-border\b/g, "") | .replace(/\bprint-no-border\b/g, "") | ||
.trim(); | .trim(); | ||
| Line 1,377: | Line 1,459: | ||
})(); | })(); | ||
// apply border preference to <html> | |||
(function () { | (function () { | ||
var htmlEl = doc.documentElement; | var htmlEl = doc.documentElement; | ||
| Line 1,389: | Line 1,472: | ||
if (htmlEl.classList) htmlEl.classList.remove("print-no-border"); | if (htmlEl.classList) htmlEl.classList.remove("print-no-border"); | ||
else | else | ||
htmlEl.className = htmlEl.className.replace( | htmlEl.className = (htmlEl.className || "").replace( | ||
/\bprint-no-border\b/g, | /\bprint-no-border\b/g, | ||
"" | "" | ||
); | ); | ||
} | } | ||
})(); | })(); | ||
// | // Glue label + body together (extra safety vs. page breaks) | ||
(function () { | (function () { | ||
var style = doc.createElement("style"); | var style = doc.createElement("style"); | ||
style. | style.textContent = | ||
"@media print{.sw-keep{break-inside:avoid;page-break-inside:avoid;}}"; | |||
doc.head.appendChild(style); | doc.head.appendChild(style); | ||
var pairs = [ | |||
[".article-label-description", ".article-description"], | |||
[".article-label-reflection", ".article-reflection"], | |||
var | [".article-label-external-reference", ".article-external-reference"], | ||
[".article-label-quote", ".article-quote"], | |||
[".article-label-modification-date", ".article-modification-date"], | |||
]; | |||
for (var i = 0; i < pairs.length; i++) { | |||
var labelSel = pairs[i][0]; | |||
var bodySel = pairs[i][1]; | |||
var labels = doc.querySelectorAll(labelSel); | |||
for (var j = 0; j < labels.length; j++) { | |||
var label = labels[j]; | |||
var body = label.nextElementSibling; | |||
if (!body || !body.matches(bodySel)) continue; | |||
var wrap = doc.createElement("div"); | |||
wrap.className = "sw-keep"; | |||
label.parentNode.insertBefore(wrap, label); | |||
wrap.appendChild(label); | |||
wrap.appendChild(body); | |||
} | |||
} | } | ||
})(); | })(); | ||
| Line 1,488: | Line 1,517: | ||
var txt = (p.textContent || "").replace(/\u00a0/g, " ").trim(); | var txt = (p.textContent || "").replace(/\u00a0/g, " ").trim(); | ||
var onlyBr = | var onlyBr = | ||
p.children && | |||
p.children.length === 1 && | p.children.length === 1 && | ||
p.firstElementChild && | p.firstElementChild && | ||
| Line 1,500: | Line 1,530: | ||
var root = doc.getElementById("article-content"); | var root = doc.getElementById("article-content"); | ||
if (root) { | if (root) { | ||
Array.prototype.slice.call(root.childNodes). | var kids = Array.prototype.slice.call(root.childNodes); | ||
for (var k = 0; k < kids.length; k++) { | |||
var n = kids[k]; | |||
if (n.nodeType === 3 && !n.textContent.replace(/\s+/g, "")) { | if (n.nodeType === 3 && !n.textContent.replace(/\s+/g, "")) { | ||
root.removeChild(n); | root.removeChild(n); | ||
} | } | ||
} | } | ||
} | } | ||
})(); | })(); | ||
// | // inline micro-tweaks for print spacing | ||
(function () { | (function () { | ||
var css = | var css = | ||
| Line 1,515: | Line 1,547: | ||
" .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-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;}" + | " .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;}" + | ||
" .article-label-description + .article-description," + | " .article-label-description + .article-description," + | ||
" .article-label-reflection + .article-reflection," + | " .article-label-reflection + .article-reflection," + | ||
| Line 1,543: | Line 1,564: | ||
})(); | })(); | ||
// link tweaks | // link tweaks (wrapping / underline) | ||
(function () { | (function () { | ||
var styleFix = doc.createElement("style"); | var styleFix = doc.createElement("style"); | ||
| Line 1,549: | Line 1,570: | ||
"@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 {.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); | doc.head.appendChild(styleFix); | ||
var refs = doc.querySelectorAll(".article-external-reference a[href]"); | var refs = doc.querySelectorAll(".article-external-reference a[href]"); | ||
Array.prototype.forEach.call(refs, function (a) { | Array.prototype.forEach.call(refs, function (a) { | ||
| Line 1,625: | Line 1,647: | ||
.then(function () { | .then(function () { | ||
// filename via document.title | // filename via document.title | ||
var desiredTitle; | |||
if (filenameOverride) { | |||
desiredTitle = filenameOverride; | |||
} else { | |||
var entryNum = ""; | var entryNum = ""; | ||
var numEl = doc.querySelector(".article-entry-number"); | var numEl = doc.querySelector(".article-entry-number"); | ||
if (numEl) { | if (numEl) { | ||
var m = (numEl.textContent || "").match(/\d+/); | |||
entryNum = m ? m[0] : ""; | |||
} | } | ||
desiredTitle = | |||
(entryNum ? entryNum + "." : "") + "softwear.directory"; | |||
} | |||
var oldIframeTitle = doc.title; | var oldIframeTitle = doc.title; | ||
var oldParentTitle = document.title; | var oldParentTitle = document.title; | ||
| Line 1,649: | Line 1,678: | ||
doc.title = desiredTitle; | doc.title = desiredTitle; | ||
document.title = desiredTitle; | document.title = desiredTitle; | ||
//window._printDoc = doc; | |||
//window._printFrame = iframe; | |||
//console.log("PRINT DOC READY", doc); | |||
//console.log("PRINT HTML", doc.body.innerHTML); | |||
iframe.contentWindow.focus(); | iframe.contentWindow.focus(); | ||
| Line 1,670: | Line 1,704: | ||
/* decide source & kick print */ | /* decide source & kick print */ | ||
function swHandlePrintChoice(id, $btn) { | function swHandlePrintChoice(id, $btn) { | ||
if ($btn && $btn.data("busy")) return; | if ($btn && $btn.data("busy")) return; | ||
if ($btn && $btn.length) $btn.data("busy", true); | if ($btn && $btn.length) $btn.data("busy", true); | ||
| Line 1,690: | Line 1,714: | ||
if (localPrintOnly.length) { | if (localPrintOnly.length) { | ||
swHidePrintUI(); | swHidePrintUI(); | ||
swBuildIframeAndPrint(localPrintOnly.prop("outerHTML"), borderPref, $btn); | swBuildIframeAndPrint(localPrintOnly.prop("outerHTML"), borderPref, $btn); | ||
return; | return; | ||
} | } | ||
// otherwise fetch by title (modal/home | // otherwise fetch by title (modal/home) | ||
var title = | var title = | ||
window.currentEntryTitle || | window.currentEntryTitle || | ||
| Line 1,709: | Line 1,732: | ||
? mw.util.getUrl(title) | ? mw.util.getUrl(title) | ||
: "/wiki/" + String(title); | : "/wiki/" + String(title); | ||
jQuery | jQuery | ||
.get(swPrintCacheBust(pageUrl)) | .get(swPrintCacheBust(pageUrl)) | ||
| Line 1,727: | Line 1,751: | ||
}); | }); | ||
} | } | ||
/* bind current choice anchors (defensive, for Entry pages) */ | |||
function swBindChoiceAnchors() { | |||
var sel = "#print-with-border, #print-no-border"; | |||
var els = document.querySelectorAll(sel); | |||
for (var i = 0; i < els.length; i++) { | |||
(function (el) { | |||
if (el.__swChoiceBound) return; | |||
el.__swChoiceBound = true; | |||
// ensure clickable/accessible | |||
try { | |||
el.style.pointerEvents = el.style.pointerEvents || "auto"; | |||
if (!el.getAttribute("role")) el.setAttribute("role", "button"); | |||
if (!el.getAttribute("tabindex")) el.setAttribute("tabindex", "0"); | |||
} catch (e) {} | |||
function fire(ev) { | |||
if (ev && ev.preventDefault) ev.preventDefault(); | |||
if (ev && ev.stopImmediatePropagation) ev.stopImmediatePropagation(); | |||
if (ev && ev.stopPropagation) ev.stopPropagation(); | |||
var $a = (window.jQuery && jQuery(el)) || null; | |||
swHandlePrintChoice(el.id, $a); | |||
return false; | |||
} | |||
// early + normal phases | |||
el.addEventListener("pointerdown", fire, true); | |||
el.addEventListener("touchstart", fire, true); | |||
el.addEventListener("mousedown", fire, true); | |||
el.addEventListener("click", fire, true); | |||
el.addEventListener("click", fire, false); | |||
if (!el.onclick) el.onclick = fire; | |||
// keyboard | |||
el.addEventListener( | |||
"keydown", | |||
function (e) { | |||
var k = e.key || e.keyCode; | |||
if (k === "Enter" || k === 13 || k === " " || k === 32) fire(e); | |||
}, | |||
true | |||
); | |||
})(els[i]); | |||
} | |||
} | |||
/* early global catcher (minimal) */ | |||
(function () { | |||
if (window.__swprintEarlyCatcher) return; | |||
window.__swprintEarlyCatcher = true; | |||
function routeEarly(ev) { | |||
var t = ev.target; | |||
if (!t || !t.closest) return; | |||
var a = t.closest("a#print-with-border, a#print-no-border"); | |||
if (!a) return; | |||
if (ev.preventDefault) ev.preventDefault(); | |||
if (ev.stopImmediatePropagation) ev.stopImmediatePropagation(); | |||
if (ev.stopPropagation) ev.stopPropagation(); | |||
swHandlePrintChoice(a.id, (window.jQuery && jQuery(a)) || null); | |||
return false; | |||
} | |||
window.addEventListener("pointerdown", routeEarly, true); | |||
window.addEventListener("touchstart", routeEarly, true); | |||
window.addEventListener("mousedown", routeEarly, true); | |||
})(); | |||
/* wiring (namespaced) */ | /* wiring (namespaced) */ | ||
| Line 1,734: | Line 1,826: | ||
"#print-button, #print-chooser, #print-options", | "#print-button, #print-chooser, #print-options", | ||
function (e) { | function (e) { | ||
// | // main [print] toggler | ||
if (jQuery(e.target).closest("#print-button").length) { | if (jQuery(e.target).closest("#print-button").length) { | ||
e.preventDefault(); | e.preventDefault(); | ||
var $chooser = swEnsurePrintChooser(); | var $chooser = swEnsurePrintChooser(); | ||
$chooser.css({ position: "absolute", zIndex: 99999 }); | |||
$chooser.css({ | |||
$chooser.toggle(); | $chooser.toggle(); | ||
var visible = $chooser.is(":visible"); | var visible = $chooser.is(":visible"); | ||
jQuery("#show-article").toggleClass("print-opts-open", visible); | jQuery("#show-article").toggleClass("print-opts-open", visible); | ||
// | // ensure anchors are bound (important on Entry pages) | ||
swBindChoiceAnchors(); | |||
return; | return; | ||
} | } | ||
// click on a choice link | // click directly on a choice link (fallback path) | ||
var $choice = jQuery(e.target).closest( | var $choice = jQuery(e.target).closest( | ||
"a#print-with-border, a#print-no-border" | "a#print-with-border, a#print-no-border" | ||
| Line 1,827: | Line 1,850: | ||
); | ); | ||
// | // map any <button> inside chooser to its host anchor | ||
jQuery(document).on( | jQuery(document).on( | ||
"click.swprintChoiceBtn2", | "click.swprintChoiceBtn2", | ||
| Line 1,867: | Line 1,860: | ||
if (!host) return; | if (!host) return; | ||
e.preventDefault(); | e.preventDefault(); | ||
swHandlePrintChoice(host.id, (window.jQuery && jQuery(host)) || null); | swHandlePrintChoice(host.id, (window.jQuery && jQuery(host)) || null); | ||
} | } | ||
); | ); | ||
// | // hide choices on ESC | ||
jQuery(document).on("keydown.swprint", function (e) { | jQuery(document).on("keydown.swprint", function (e) { | ||
if (e && e.keyCode === 27) swHidePrintUI(); | if (e && e.keyCode === 27) { | ||
swHidePrintUI(); | |||
hidePrintSelectionOptions(); | |||
} | |||
}); | }); | ||
// toggle filtered print options | |||
jQuery(document).on("click", ".print-selection-toggle", function (e) { | |||
e.preventDefault(); | |||
jQuery("#print-selection-options").toggle(); | |||
}); | |||
// run filtered batch print | |||
jQuery(document).on( | |||
"click", | |||
".print-selection-border, .print-selection-no-border", | |||
function (e) { | |||
e.preventDefault(); | |||
var $btn = jQuery(this); | |||
var borderPref = $btn.hasClass("print-selection-no-border") | |||
? "without" | |||
: "with"; | |||
// disable all related buttons | |||
jQuery(".print-selection-border, .print-selection-no-border, .print-selection-toggle") | |||
.prop("disabled", true) | |||
.css("opacity", "0.5"); | |||
// change ONLY clicked button text (native feeling) | |||
var originalText = $btn.text(); | |||
$btn.text("working…"); | |||
swHandleBatchPrint(borderPref); | |||
// optional reset (if user comes back) | |||
setTimeout(function () { | |||
$btn.text(originalText); | |||
jQuery(".print-selection-border, .print-selection-no-border, .print-selection-toggle") | |||
.prop("disabled", false) | |||
.css("opacity", ""); | |||
}, 2000); | |||
} | |||
); | |||
/* ---------- /Softwear PRINT ---------- */ | /* ---------- /Softwear PRINT ---------- */ | ||
| Line 1,942: | Line 1,976: | ||
} | } | ||
if ( | // paragraph-formatting block | ||
if (jQuery("#show-article-wrapper-entry").length) { | |||
function formatParagraphs(text) { | function formatParagraphs(text) { | ||
var | // split on newlines, drop empty lines, wrap each in <p> | ||
var parts = String(text || "").split("\n"); | |||
var out = []; | |||
for (var i = 0; i < parts.length; i++) { | |||
var p = parts[i].replace(/^\s+|\s+$/g, ""); | |||
if (p) out.push("<p>" + p + "</p>"); | |||
} | |||
return out.join(""); | |||
} | } | ||
jQuery( | |||
"#show-article .article-description, #show-article .article-reflection" | |||
var | ).each(function () { | ||
var $el = jQuery(this); | |||
if ($el.children("p").length > 0) return; // already formatted by PageForms | |||
var rawText = $el.text(); | |||
$el.html(formatParagraphs(rawText)); | |||
}); | |||
var | |||
$ | |||
} | |||
} | } | ||
| Line 2,099: | Line 2,128: | ||
} | } | ||
}); | }); | ||
updatePrintSelectionUI(); | |||
hidePrintSelectionOptions(); | |||
}); | }); | ||