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 === */  |    /* === SW PRINT: native fallback for Entry pages (ES5-safe) === */  | ||
   (function () {  |    (function () {  | ||
     //   |      // prevent double-binding  | ||
     if (window.__swPrintNativeBound) return;  |      if (window.__swPrintNativeBound) {  | ||
      return;  | |||
    }  | |||
     window.__swPrintNativeBound = true;  |      window.__swPrintNativeBound = true;  | ||
     //   |      // ---- tiny helpers ----  | ||
     function ensurePrintChooserNative() {  |      function ensurePrintChooserNative() {  | ||
       var chooser = document.getElementById("print-chooser");  |        var chooser = document.getElementById("print-chooser");  | ||
| Line 1,701: | Line 1,703: | ||
       var article = document.getElementById("show-article");  |        var article = document.getElementById("show-article");  | ||
       if (article) {  |        if (article) {  | ||
         if (want) article.classList.add("print-opts-open");  |          if (want) {  | ||
         else article.classList.remove("print-opts-open");  |           article.classList.add("print-opts-open");  | ||
         } else {  | |||
          article.classList.remove("print-opts-open");  | |||
        }  | |||
      }  | |||
      if (window.console && console.log) {  | |||
        console.log("[swprint-native] chooser", want ? "shown" : "hidden");  | |||
      }  | |||
    }  | |||
    function safeCacheBust(url) {  | |||
      try {  | |||
        if (typeof cacheBust === "function") {  | |||
          return cacheBust(url);  | |||
        }  | |||
      } catch (e) {  | |||
        /* ignore */  | |||
       }  |        }  | ||
       var sep = url.indexOf("?") > -1 ? "&" : "?";  | |||
      return url + sep + "_=" + new Date().getTime();  | |||
     }  |      }  | ||
     //   |      // ---- main flow: start printing with preference ----  | ||
     function swStartPrint(borderPref) {  |      function swStartPrint(borderPref) {  | ||
       console.log("[swprint-native] start with pref:", borderPref);  |        if (window.console && console.log) {  | ||
        console.log("[swprint-native] start with pref:", borderPref);  | |||
      }  | |||
       try {  |        try {  | ||
         preloadFontForPrint   |          if (typeof preloadFontForPrint === "function") {  | ||
          preloadFontForPrint();  | |||
        }  | |||
       } catch (e) {}  |        } catch (e) {}  | ||
       // 1) Prefer local .print-only (Entry page)  |        // 1) Prefer local .print-only (Entry page content already on page)  | ||
       var local = document.querySelector(".print-only");  |        var local = document.querySelector(".print-only");  | ||
       if (local) {  |        if (local) {  | ||
         console.log("[swprint-native] using local .print-only");  |          if (window.console && console.log) {  | ||
          console.log("[swprint-native] using local .print-only");  | |||
        }  | |||
         toggleChooser(false);  |          toggleChooser(false);  | ||
         buildIframeAndPrint(local.outerHTML, borderPref);  | |||
        return;  | |||
       }  |        }  | ||
       // 2) Otherwise fetch by title (modal /   |        // 2) Otherwise, fetch by title (modal / people page flow)  | ||
       var title =  |        var title = null;  | ||
         window.currentEntryTitle   |       if (  | ||
         (window.mw &&  |         typeof window.currentEntryTitle === "string" &&  | ||
         window.currentEntryTitle  | |||
      ) {  | |||
         title = window.currentEntryTitle;  | |||
      } else if (  | |||
        window.mw &&  | |||
        mw.config &&  | |||
        typeof mw.config.get === "function"  | |||
      ) {  | |||
        title = mw.config.get("wgPageName");  | |||
      }  | |||
       if (  |        if (  | ||
| Line 1,735: | Line 1,768: | ||
         !(window.mw && mw.util && typeof mw.util.getUrl === "function")  |          !(window.mw && mw.util && typeof mw.util.getUrl === "function")  | ||
       ) {  |        ) {  | ||
         console.warn(  |          if (window.console && console.warn) {  | ||
          console.warn(  | |||
            "[swprint-native] no title/mw.util; fallback to window.print()"  | |||
          );  | |||
         }  | |||
        window.print();  | |||
        return;  | |||
       }  |        }  | ||
       var url = mw.util.getUrl(title);  |        var url = mw.util.getUrl(title);  | ||
       url = safeCacheBust(url);  | |||
       if (window.console && console.log) {  | |||
        console.log("[swprint-native] fetching:", url);  | |||
      }  | |||
       fetch(url, { credentials: "same-origin" })  |        // Use fetch if present; fall back to XHR  | ||
      if (window.fetch) {  | |||
        fetch(url, { credentials: "same-origin" })  | |||
          .then(function (r) {  | |||
            return r.text();  | |||
          })  | |||
          .then(function (html) {  | |||
           var   |             handleFetchedHtml(html, borderPref);  | ||
           if (  |            })  | ||
             console.warn(  |           .catch(function (err) {  | ||
            if (window.console && console.warn) {  | |||
              console.warn(  | |||
                "[swprint-native] fetch failed; window.print()",  | |||
                err  | |||
              );  | |||
            }  | |||
            window.print();  | |||
           });  | |||
      } else {  | |||
        var xhr = new XMLHttpRequest();  | |||
        xhr.open("GET", url, true);  | |||
        xhr.withCredentials = true;  | |||
        xhr.onreadystatechange = function () {  | |||
           if (xhr.readyState === 4) {  | |||
            if (xhr.status >= 200 && xhr.status < 300) {  | |||
              handleFetchedHtml(xhr.responseText, borderPref);  | |||
             } else {  | |||
              if (window.console && console.warn) {  | |||
                console.warn(  | |||
                  "[swprint-native] XHR failed; window.print()",  | |||
                  xhr.status  | |||
                );  | |||
              }  | |||
              window.print();  | |||
            }  | |||
           }  |            }  | ||
         };  | |||
         xhr.send(null);  | |||
         }  |       }  | ||
         .  | |||
     }  |      }  | ||
     //   |     function handleFetchedHtml(html, borderPref) {  | ||
      var tmp = document.createElement("div");  | |||
      tmp.innerHTML = html;  | |||
      var printOnly = tmp.querySelector(".print-only");  | |||
      if (!printOnly) {  | |||
        if (window.console && console.warn) {  | |||
          console.warn(  | |||
            "[swprint-native] no .print-only in fetched page; window.print()"  | |||
          );  | |||
        }  | |||
        window.print();  | |||
        return;  | |||
      }  | |||
      toggleChooser(false);  | |||
      buildIframeAndPrint(printOnly.outerHTML, borderPref);  | |||
    }  | |||
     // ---- iframe build + print (ES5) ----  | |||
     function buildIframeAndPrint(printHtml, borderPref) {  |      function buildIframeAndPrint(printHtml, borderPref) {  | ||
       console.log("[swprint-native] buildIframeAndPrint()");  |        if (window.console && console.log) {  | ||
        console.log("[swprint-native] buildIframeAndPrint()");  | |||
      }  | |||
       var iframe = document.createElement("iframe");  |        var iframe = document.createElement("iframe");  | ||
| Line 1,796: | Line 1,869: | ||
       var cssUrl =  |        var cssUrl =  | ||
         "/index.php?title=MediaWiki:Print.css&action=raw&ctype=text/css";  |          "/index.php?title=MediaWiki:Print.css&action=raw&ctype=text/css";  | ||
       cssUrl = safeCacheBust(cssUrl);  | |||
       var linkCss = doc.createElement("link");  |        var linkCss = doc.createElement("link");  | ||
       linkCss.rel = "stylesheet";  |        linkCss.rel = "stylesheet";  | ||
       linkCss.href = cssUrl;  |        linkCss.href = cssUrl;  | ||
       var cssLoaded = new Promise(function (  | |||
       var cssLoaded = new Promise(function (resolve) {  | |||
         linkCss.onload = function () {  |          linkCss.onload = function () {  | ||
           console.log("[swprint-native] print CSS loaded");  |            if (window.console && console.log) {  | ||
            console.log("[swprint-native] print CSS loaded");  | |||
           }  | |||
          resolve();  | |||
         };  |          };  | ||
         linkCss.onerror = function () {  |          linkCss.onerror = function () {  | ||
           console.warn("[swprint-native] print CSS failed");  |            if (window.console && console.warn) {  | ||
            console.warn("[swprint-native] print CSS failed");  | |||
           }  | |||
          resolve();  | |||
         };  |          };  | ||
       });  |        });  | ||
| Line 1,824: | Line 1,900: | ||
       doc.head.appendChild(linkCss);  |        doc.head.appendChild(linkCss);  | ||
      // content  | |||
       doc.body.innerHTML = printHtml;  |        doc.body.innerHTML = printHtml;  | ||
       // border pref   |        // border pref  | ||
       var root = doc.documentElement;  |        var root = doc.documentElement;  | ||
       if (borderPref === "without") root.classList.add("print-no-border");  |        if (borderPref === "without") {  | ||
       else root.classList.remove("print-no-border");  |         root.classList.add("print-no-border");  | ||
       console.log("[swprint-native] borderPref applied:", borderPref);  |        } else {  | ||
        root.classList.remove("print-no-border");  | |||
       }  | |||
      if (window.console && console.log) {  | |||
        console.log("[swprint-native] borderPref applied:", borderPref);  | |||
      }  | |||
       //   |        // minimal inline tweaks  | ||
       var style = doc.createElement("style");  |        var style = doc.createElement("style");  | ||
       style.  |        style.type = "text/css";  | ||
         "@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}}";  |       style.appendChild(  | ||
         doc.createTextNode(  | |||
          "@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);  |        doc.head.appendChild(style);  | ||
       var styleFix = doc.createElement("style");  |        var styleFix = doc.createElement("style");  | ||
       styleFix.  |        styleFix.type = "text/css";  | ||
         "@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}}";  |       styleFix.appendChild(  | ||
         doc.createTextNode(  | |||
          "@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);  | ||
       // wait helpers   |        // wait helpers  | ||
       function nextFrame() {  |        function nextFrame(resolve) {  | ||
         (iframe.contentWindow.requestAnimationFrame || setTimeout)(resolve, 0);  | |||
       }  |        }  | ||
      var waitNextFrame = new Promise(function (resolve) {  | |||
        nextFrame(resolve);  | |||
      });  | |||
       var waitFonts =  |        var waitFonts =  | ||
         doc.fonts && doc.fonts.ready  |          doc.fonts && doc.fonts.ready  | ||
           ? Promise.race([  |            ? Promise.race([  | ||
               doc.fonts.ready,  |                doc.fonts.ready,  | ||
               new Promise((r)   |                new Promise(function (r) {  | ||
                setTimeout(r, 1200);  | |||
              }),  | |||
             ])  |              ])  | ||
           : Promise.resolve();  |            : Promise.resolve();  | ||
       Promise.all([cssLoaded, waitFonts,   |        Promise.all([cssLoaded, waitFonts, waitNextFrame]).then(function () {  | ||
         console.log("[swprint-native] resources ready; print()");  |          if (window.console && console.log) {  | ||
          console.log("[swprint-native] resources ready; print()");  | |||
         }  | |||
         var numEl = doc.querySelector(".article-entry-number");  |          var numEl = doc.querySelector(".article-entry-number");  | ||
         var entryNum = "";  |          var entryNum = "";  | ||
| Line 1,868: | Line 1,963: | ||
         var desiredTitle =  |          var desiredTitle =  | ||
           (entryNum ? entryNum + "." : "") + "softwear.directory";  |            (entryNum ? entryNum + "." : "") + "softwear.directory";  | ||
         var oldIframeTitle = doc.title;  |          var oldIframeTitle = doc.title;  | ||
         var oldParentTitle = document.title;  |          var oldParentTitle = document.title;  | ||
| Line 1,877: | Line 1,973: | ||
           } catch (e) {}  |            } catch (e) {}  | ||
           setTimeout(function () {  |            setTimeout(function () {  | ||
             if (iframe.parentNode) iframe.parentNode.removeChild(iframe);  |              if (iframe.parentNode) {  | ||
              iframe.parentNode.removeChild(iframe);  | |||
            }  | |||
           }, 100);  |            }, 100);  | ||
           console.log("[swprint-native] afterprint cleanup");  |            if (window.console && console.log) {  | ||
            console.log("[swprint-native] afterprint cleanup");  | |||
          }  | |||
         };  |          };  | ||
| Line 1,888: | Line 1,988: | ||
         iframe.contentWindow.print();  |          iframe.contentWindow.print();  | ||
        // safety cleanup if onafterprint never fires  | |||
         setTimeout(function () {  |          setTimeout(function () {  | ||
           try {  |            try {  | ||
| Line 1,893: | Line 1,994: | ||
             document.title = oldParentTitle;  |              document.title = oldParentTitle;  | ||
           } catch (e) {}  |            } catch (e) {}  | ||
           if (iframe.parentNode) iframe.parentNode.removeChild(iframe);  |            if (iframe.parentNode) {  | ||
           console.log("[swprint-native] timeout cleanup");  |             iframe.parentNode.removeChild(iframe);  | ||
         },   |            }  | ||
          if (window.console && console.log) {  | |||
            console.log("[swprint-native] timeout cleanup");  | |||
          }  | |||
         }, 1500);  | |||
       });  |        });  | ||
     }  |      }  | ||
     //   |      // ---- bind native clicks ----  | ||
     var printBtn = document.getElementById("print-button");  |      var printBtn = document.getElementById("print-button");  | ||
     if (printBtn) {  |      if (printBtn) {  | ||
| Line 1,905: | Line 2,010: | ||
         "click",  |          "click",  | ||
         function (e) {  |          function (e) {  | ||
           e.preventDefault();  |            if (e && e.preventDefault) {  | ||
           console.log("[swprint-native] print-button clicked");  |             e.preventDefault();  | ||
           }  | |||
          if (window.console && console.log) {  | |||
            console.log("[swprint-native] print-button clicked");  | |||
          }  | |||
           toggleChooser();  |            toggleChooser();  | ||
         },  |          },  | ||
| Line 1,913: | Line 2,022: | ||
     }  |      }  | ||
     function onChoice(e) {  |      function onChoice(e) {  | ||
       var   |        var t = e.target || e.srcElement;  | ||
       if (!a) return;  |       var a = null;  | ||
       if (  |       // emulate closest("a") in ES5  | ||
       e.preventDefault();  |       while (t && t !== document) {  | ||
       var pref =   |         if (t.tagName && t.tagName.toLowerCase() === "a") {  | ||
       console.log("[swprint-native] choice clicked:", pref);  |           a = t;  | ||
          break;  | |||
        }  | |||
        t = t.parentNode;  | |||
      }  | |||
       if (!a) {  | |||
        return;  | |||
      }  | |||
      var id = a.id || "";  | |||
       if (id !== "print-with-border" && id !== "print-no-border") {  | |||
        return;  | |||
       }  | |||
      if (e && e.preventDefault) {  | |||
        e.preventDefault();  | |||
      }  | |||
       var pref = id === "print-no-border" ? "without" : "with";  | |||
       if (window.console && console.log) {  | |||
        console.log("[swprint-native] choice clicked:", pref);  | |||
      }  | |||
       swStartPrint(pref);  |        swStartPrint(pref);  | ||
     }  |      }  | ||
     // if already   |      // bind existing anchors (if already in DOM)  | ||
     var aWith = document.getElementById("print-with-border");  | |||
       var   |     if (aWith) {  | ||
       aWith.addEventListener("click", onChoice, false);  | |||
     }  |     }  | ||
    var aNo = document.getElementById("print-no-border");  | |||
    if (aNo) {  | |||
      aNo.addEventListener("click", onChoice, false);  | |||
     }  | |||
     // and delegate for dynamically created chooser  |      // and delegate for dynamically created chooser  | ||
     document.addEventListener("click", onChoice, false);  |      document.addEventListener("click", onChoice, false);  | ||
     console.log("[swprint-native] fallback bound");  |      if (window.console && console.log) {  | ||
      console.log("[swprint-native] fallback bound");  | |||
    }  | |||
   })();  |    })();  | ||