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) {  | ||