MediaWiki:Common.js: Difference between revisions

Jump to navigation Jump to search
no edit summary
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 () {
     // guard so we don’t double-bind if this block is included twice
     // prevent double-binding
     if (window.__swPrintNativeBound) return;
     if (window.__swPrintNativeBound) {
      return;
    }
     window.__swPrintNativeBound = true;
     window.__swPrintNativeBound = true;


     // util: create/toggle the chooser safely (no jQuery required)
     // ---- 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 */
       }
       }
       console.log("[swprint-native] chooser", want ? "shown" : "hidden");
       var sep = url.indexOf("?") > -1 ? "&" : "?";
      return url + sep + "_=" + new Date().getTime();
     }
     }


     // MAIN: start print with pref
     // ---- 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 && 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);
         return buildIframeAndPrint(local.outerHTML, borderPref);
         buildIframeAndPrint(local.outerHTML, borderPref);
        return;
       }
       }


       // 2) Otherwise fetch by title (modal / other pages)
       // 2) Otherwise, fetch by title (modal / people page flow)
       var title =
       var title = null;
         window.currentEntryTitle ||
      if (
         (window.mw &&
        typeof window.currentEntryTitle === "string" &&
          mw.config &&
         window.currentEntryTitle
          typeof mw.config.get === "function" &&
      ) {
          mw.config.get("wgPageName"));
         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) {
          "[swprint-native] no title/mw.util; falling back to window.print()"
          console.warn(
        );
            "[swprint-native] no title/mw.util; fallback to window.print()"
         return window.print();
          );
         }
        window.print();
        return;
       }
       }


       var url = mw.util.getUrl(title);
       var url = mw.util.getUrl(title);
       try {
       url = safeCacheBust(url);
        url = typeof cacheBust === "function" ? cacheBust(url) : url;
       if (window.console && console.log) {
       } catch (e) {}
        console.log("[swprint-native] fetching:", url);
      console.log("[swprint-native] fetching:", url);
      }


       fetch(url, { credentials: "same-origin" })
       // Use fetch if present; fall back to XHR
        .then(function (r) {
      if (window.fetch) {
          return r.text();
        fetch(url, { credentials: "same-origin" })
        })
          .then(function (r) {
        .then(function (html) {
            return r.text();
           var tmp = document.createElement("div");
          })
          tmp.innerHTML = html;
          .then(function (html) {
           var printOnly = tmp.querySelector(".print-only");
            handleFetchedHtml(html, borderPref);
           if (!printOnly) {
           })
             console.warn(
          .catch(function (err) {
              "[swprint-native] no .print-only in fetched page; window.print()"
            if (window.console && console.warn) {
            );
              console.warn(
            return window.print();
                "[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();
            }
           }
           }
          toggleChooser(false);
         };
          buildIframeAndPrint(printOnly.outerHTML, borderPref);
         xhr.send(null);
         })
      }
         .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 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";
       try {
       cssUrl = safeCacheBust(cssUrl);
        cssUrl = typeof cacheBust === "function" ? cacheBust(cssUrl) : cssUrl;
      } catch (e) {}


       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 (res) {
 
       var cssLoaded = new Promise(function (resolve) {
         linkCss.onload = function () {
         linkCss.onload = function () {
           console.log("[swprint-native] print CSS loaded");
           if (window.console && console.log) {
           res();
            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) {
           res();
            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 class on <html>
       // 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);
      }


       // small inline tweaks (same as your version)
       // minimal inline tweaks
       var style = doc.createElement("style");
       var style = doc.createElement("style");
       style.textContent =
       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.textContent =
       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 (minimal)
       // wait helpers
       function nextFrame() {
       function nextFrame(resolve) {
         return new Promise(function (r) {
         (iframe.contentWindow.requestAnimationFrame || setTimeout)(resolve, 0);
          (iframe.contentWindow.requestAnimationFrame || setTimeout)(r, 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) => setTimeout(r, 1200)),
               new Promise(function (r) {
                setTimeout(r, 1200);
              }),
             ])
             ])
           : Promise.resolve();
           : Promise.resolve();


       Promise.all([cssLoaded, waitFonts, nextFrame()]).then(function () {
       Promise.all([cssLoaded, waitFonts, waitNextFrame]).then(function () {
         console.log("[swprint-native] resources ready; print()");
         if (window.console && console.log) {
         // filename by title
          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);
         }, 1200);
           }
          if (window.console && console.log) {
            console.log("[swprint-native] timeout cleanup");
          }
         }, 1500);
       });
       });
     }
     }


     // Bind native click to PRINT button (toggle choices)
     // ---- 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:
     }
     }


    // Bind native clicks to choices (border/no-border)
     function onChoice(e) {
     function onChoice(e) {
       var a = e.target.closest && e.target.closest("a");
       var t = e.target || e.srcElement;
       if (!a) return;
      var a = null;
       if (a.id !== "print-with-border" && a.id !== "print-no-border") return;
      // emulate closest("a") in ES5
       e.preventDefault();
      while (t && t !== document) {
       var pref = a.id === "print-no-border" ? "without" : "with";
        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 present
     // bind existing anchors (if already in DOM)
     ["print-with-border", "print-no-border"].forEach(function (id) {
     var aWith = document.getElementById("print-with-border");
       var el = document.getElementById(id);
    if (aWith) {
      if (el) el.addEventListener("click", onChoice, false);
       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");
    }
   })();
   })();


Navigation menu