MediaWiki:Common.js: Difference between revisions

Jump to navigation Jump to search
no edit summary
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 three
   // 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 = this.id;
      var rawId = this.id; // in case you clicked the element with the id directly
       var id = ($anchor.attr("id") || rawId || "").trim();


       // If the main [print] is clicked, just toggle the chooser and stop.
      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();


        // push the title row down when options are visible
         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; // <-- don't start printing yet
 
        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;
       }
       }


      // otherwise it's one of the two choices; proceed with the print flow…
       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);


      // decide the border preference from the clicked button id
       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();


       // 1) FIRST: if the page already has a .print-only (Entry page), use it and bail.
       // 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");
        // optional: hide chooser when starting print
         $("#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; // done; no fetch needed
         return;
       }
       }


       // 2) OTHERWISE: we’re in modal/home list flow, fetch by title
       // 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()");
          "[print] no title available; 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);
            "[print] .print-only found in fetched page:",
            $print.length
          );
           if (!$print.length) {
           if (!$print.length) {
             console.warn("[print] no .print-only found; fallback print()");
             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 to this click so it can see borderPref and $btn ----
       // 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 (Chrome becomes much happier)
         // 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") {
             if (rootHtml.classList) rootHtml.classList.add("print-no-border");
             rootHtml.classList
            else if (!/\bprint-no-border\b/.test(rootHtml.className))
              ? rootHtml.classList.add("print-no-border")
              rootHtml.className += " print-no-border";
              : (rootHtml.className += " print-no-border");
           } else {
           } else {
             if (rootHtml.classList)
             rootHtml.classList
               rootHtml.classList.remove("print-no-border");
               ? rootHtml.classList.remove("print-no-border")
            else
               : (rootHtml.className = rootHtml.className.replace(
               rootHtml.className = rootHtml.className.replace(
                  /\bprint-no-border\b/g,
                /\bprint-no-border\b/g,
                  ""
                ""
                ));
              );
           }
           }
          console.log("[print] borderPref applied:", borderPref);
         })();
         })();


         // CLEAN: remove empty paragraphs/whitespace nodes that create phantom gaps
         // 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 print-tweaks CSS
         // 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-label-description + .article-description," +
            "  .article-label-reflection + .article-reflection," +
            "  .article-label-external-reference + .article-external-reference," +
            "  .article-label-quote + .article-quote," +
            "  .article-label-modification-date + .article-modification-date{margin-top:0!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 = doc.createElement("style");
         var linkCssFix =
        linkCssFix.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}}";
           "@media print {\n" +
        var styleFix = doc.createElement("style");
          "  .article-external-reference a,\n" +
        styleFix.textContent = linkCssFix;
          "  .link-pdf a { white-space: nowrap !important; word-break: normal !important; overflow-wrap: normal !important; text-decoration: underline; }\n" +
         doc.head.appendChild(styleFix);
          "  .article-external-reference { overflow-wrap: anywhere; word-break: break-word; }\n" +
          "  a[href] { position: relative; }\n" +
          "}\n";
         doc.head.appendChild(linkCssFix);


         (function () {
         (function () {
Line 1,561: Line 1,571:
               }
               }
             }
             }
            a.style.whiteSpace = "nowrap";
            a.style.wordBreak = "normal";
            a.style.overflowWrap = "normal";
          });
          doc.querySelectorAll(".link-pdf a[href]").forEach(function (a) {
             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 () {
         ])
          try {
          .then(function () {
            // Filename via document.title
            console.log("[print] resources ready; calling print()");
            var entryNum = "";
            try {
            var numEl = doc.querySelector(".article-entry-number");
              // Filename via document.title
            if (numEl) {
              var entryNum = "";
              var m = (numEl.textContent || "").match(/\d+/);
              var numEl = doc.querySelector(".article-entry-number");
              entryNum = m ? m[0] : "";
              if (numEl) {
            }
                var m = (numEl.textContent || "").match(/\d+/);
            var desiredTitle =
                entryNum = m ? m[0] : "";
              (entryNum ? entryNum + "." : "") + "softwear.directory";
              }
              var desiredTitle =
                (entryNum ? entryNum + "." : "") + "softwear.directory";


            var oldIframeTitle = doc.title;
              var oldIframeTitle = doc.title;
            var oldParentTitle = document.title;
              var oldParentTitle = document.title;


            iframe.contentWindow.onafterprint = function () {
              iframe.contentWindow.onafterprint = function () {
              try {
                try {
                doc.title = oldIframeTitle;
                  doc.title = oldIframeTitle;
                document.title = oldParentTitle;
                  document.title = oldParentTitle;
              } catch (e) {}
                } catch (e) {}
              setTimeout(function () {
                setTimeout(function () {
                if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
                  if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
              }, 100);
                }, 100);
              $btn.data("busy", false);
                $btn.data("busy", false);
            };
                console.log("[print] afterprint cleanup done");
              };


            doc.title = desiredTitle;
              doc.title = desiredTitle;
            document.title = desiredTitle;
              document.title = desiredTitle;


            iframe.contentWindow.focus();
              iframe.contentWindow.focus();
            iframe.contentWindow.print();
              iframe.contentWindow.print();


            setTimeout(function () {
              // Safety cleanup if onafterprint never fires
              try {
              setTimeout(function () {
                doc.title = oldIframeTitle;
                try {
                document.title = oldParentTitle;
                  doc.title = oldIframeTitle;
              } catch (e) {}
                  document.title = oldParentTitle;
              if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
                } 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);
             }, 1000);
             }
           } catch (err) {
          })
             console.warn("[print] failed before print:", err);
           .catch(function (err) {
             console.warn("[print] Promise chain error:", err);
             $btn.data("busy", false);
             $btn.data("busy", false);
           }
           });
        });
       }
       }
     }
     }

Navigation menu