MediaWiki:Common.js: Difference between revisions

Jump to navigation Jump to search
3,929 bytes removed ,  Yesterday at 11:53
no edit summary
No edit summary
No edit summary
Line 1,370: Line 1,370:


         // Remove “empty” optional sections so they don’t leave gaps in print.
         // Remove “empty” optional sections so they don’t leave gaps in print.
         // --- DEBUG + robust removal of empty sections in the print iframe ---
         // --- Compact vertical spacing & report gaps in the print iframe ---
         (function debugAndTidyPrint(doc) {
         (function compactAndReport(doc) {
           // Toggle verbose output / colored outlines
           // 1) Trim margins everywhere in #article-content. Rely on your hairline padding instead.
           var DEBUG_PRINT = true;
           var css = doc.createElement("style");
          css.textContent =
            "@media print{" +
            "#article-content>*{margin-top:0!important;margin-bottom:0!important}" +
            // keep your hairline look but ensure it’s not huge
            ".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:6px!important}" +
            // remove hairline on the very last child to avoid a trailing gap
            "#article-content>:last-child{padding-bottom:0!important}" +
            "#article-content>:last-child::after{content:none!important}" +
            // kill any accidental block that’s truly empty (divs/spans)
            "#article-content div:empty,#article-content p:empty{display:none!important;height:0!important;padding:0!important;border:0!important}" +
            "}";
          doc.head.appendChild(css);


           // 0) Add a tag so we can scope debug styles safely
           // 2) Extra cleanup: remove empty DIV shells that still contain only whitespace
           doc.documentElement.setAttribute("data-print-ifr", "1");
           (function removeEmptyDivs() {
 
             var nodes = doc.querySelectorAll("#article-content div");
          // 1) Debug CSS (visualize what the iframe thinks exists)
             for (var i = 0; i < nodes.length; i++) {
          if (DEBUG_PRINT) {
               var el = nodes[i];
             var dbg = doc.createElement("style");
               if (!el.firstElementChild) {
             dbg.textContent =
                var t = (el.textContent || "")
              "[data-print-ifr] .article-label-description{outline:1px solid #1e90ff!important}" +
                  .replace(/\u00A0/g, " ")
              "[data-print-ifr] .article-description{outline:1px dashed #1e90ff!important}" +
                  .replace(/\u200B/g, "")
              "[data-print-ifr] .article-label-reflection{outline:1px solid #aa00ff!important}" +
                  .trim();
               "[data-print-ifr] .article-reflection{outline:1px dashed #aa00ff!important}" +
                if (!t && el.parentNode) el.parentNode.removeChild(el);
               "[data-print-ifr] .article-label-external-reference{outline:1px solid #00aa88!important}" +
              "[data-print-ifr] .article-external-reference{outline:1px dashed #00aa88!important}" +
              "[data-print-ifr] .article-label-quote{outline:1px solid #ff8800!important}" +
              "[data-print-ifr] .article-quote{outline:1px dashed #ff8800!important}" +
              "[data-print-ifr] .article-images{outline:1px dashed #e91e63!important}" +
              // show the last-child hairline situation
              "@media print{" +
              "[data-print-ifr] #article-content>:last-child{outline:2px solid red!important}" +
              "}";
            doc.head.appendChild(dbg);
          }
 
          // 2) Helpers
          function cleanText(node) {
            var txt = (node.textContent || "")
              .replace(/\u00A0/g, " ") // nbsp
              .replace(/\u200B/g, "") // zero-width
              .replace(/\s+/g, " ") // collapse
              .trim();
            return txt;
          }
 
          function looksEmptyBlock(el) {
            if (!el) return true;
 
            // If it has meaningful children, it's not empty
            if (
              el.querySelector("img,video,audio,iframe,svg,object,embed,canvas")
            )
              return false;
            if (el.querySelector("a[href]")) return false;
 
            // Clone to strip <br> and empty <p> safely
            var c = el.cloneNode(true),
              i;
 
            // remove <br>
            var brs = c.getElementsByTagName("br");
            for (i = brs.length - 1; i >= 0; i--)
              brs[i].parentNode.removeChild(brs[i]);
 
            // remove empty/whitespace-only <p>
            var ps = c.getElementsByTagName("p");
            for (i = ps.length - 1; i >= 0; i--) {
              var t = cleanText(ps[i]);
              if (!t) ps[i].parentNode.removeChild(ps[i]);
            }
 
            return cleanText(c) === "";
          }
 
          function collapsePair(labelSel, blockSel) {
            var block = doc.querySelector(blockSel);
            var label = doc.querySelector(labelSel);
            if (!block && !label) {
              if (DEBUG_PRINT)
                console.log("[print] pair missing:", labelSel, blockSel);
              return;
            }
 
            var empty = block ? looksEmptyBlock(block) : true;
 
            if (DEBUG_PRINT) {
              console.log("[print] check", blockSel, {
                exists: !!block,
                empty: empty,
                textLen: block ? cleanText(block).length : 0,
              });
            }
 
            if (empty) {
              if (label && label.parentNode)
                label.parentNode.removeChild(label);
              if (block && block.parentNode)
                block.parentNode.removeChild(block);
            }
          }
 
          // 3) Images: drop wrapper if no usable <img src>
          (function () {
            var wrap = doc.querySelector(".article-images");
            if (!wrap) return;
            var imgs = wrap.getElementsByTagName("img");
            var hasSrc = false,
              i;
            for (i = 0; i < imgs.length; i++) {
              var s = imgs[i].getAttribute("src");
              if (s && /\S/.test(s)) {
                hasSrc = true;
                break;
               }
               }
             }
             }
            if (DEBUG_PRINT)
              console.log(
                "[print] images wrapper, hasImg:",
                hasSrc,
                "count:",
                imgs.length
              );
            if (!hasSrc && wrap.parentNode) wrap.parentNode.removeChild(wrap);
           })();
           })();


           // 4) Collapse optional sections
           // 3) GAP reporter — logs where any unexpected space (>8px) occurs between siblings
          collapsePair(".article-label-description", ".article-description");
           (function reportGaps() {
          collapsePair(".article-label-reflection", ".article-reflection");
             var container = doc.getElementById("article-content");
          collapsePair(
             if (!container) return;
            ".article-label-external-reference",
             var kids = [];
            ".article-external-reference"
             for (
          );
              var n = container.firstElementChild;
          collapsePair(".article-label-quote", ".article-quote");
               n;
 
              n = n.nextElementSibling
          // 5) Metadata grid: remove if all values empty
            ) {
           (function () {
              // skip nodes that are display:none (offsetParent null) or zero-height
             var meta = doc.querySelector(".article-metadata");
               if (!n.offsetParent || n.offsetHeight === 0) continue;
             if (!meta) return;
              kids.push(n);
             var vals = meta.querySelectorAll(".article-metadata-value");
             var allEmpty = true,
               i;
            for (i = 0; i < vals.length; i++) {
               if (!looksEmptyBlock(vals[i])) {
                allEmpty = false;
                break;
              }
             }
             }
             if (DEBUG_PRINT)
             for (var i = 0; i < kids.length - 1; i++) {
               console.log("[print] metadata allEmpty:", allEmpty);
               var a = kids[i],
            if (allEmpty && meta.parentNode) meta.parentNode.removeChild(meta);
                b = kids[i + 1];
          })();
              var gap =
 
                b.getBoundingClientRect().top -
          // 6) Link bar: remove if it has no anchors
                (a.getBoundingClientRect().top +
          (function () {
                  a.getBoundingClientRect().height);
            var bar = doc.querySelector(".link-pdf");
               if (gap > 8) {
            var hasLink =
                console.log(
               bar && bar.querySelector && bar.querySelector("a[href]");
                  "[print] GAP",
            if (DEBUG_PRINT)
                  Math.round(gap) + "px",
              console.log("[print] link-pdf hasLink:", !!hasLink);
                  "between",
            if (bar && !hasLink && bar.parentNode)
                   a.className || a.tagName,
              bar.parentNode.removeChild(bar);
                  "",
          })();
                  b.className || b.tagName
 
                 );
          // 7) Kill truly empty <p> shells that still occupy height
          (function () {
            var ps = doc.querySelectorAll("#article-content p");
            for (var i = 0; i < ps.length; i++) {
              var p = ps[i];
              if (!p.children.length && cleanText(p) === "" && p.parentNode) {
                if (DEBUG_PRINT)
                   console.log(
                    "[print] remove empty <p>",
                    p.className || "(no class)"
                  );
                 p.parentNode.removeChild(p);
               }
               }
             }
             }
          })();
          // 8) Remove trailing hairline padding on last visible block
          (function () {
            var fix = doc.createElement("style");
            fix.textContent =
              "@media print{" +
              "#article-content>:last-child{padding-bottom:0!important}" +
              "#article-content>:last-child::after{content:none!important}" +
              "}";
            doc.head.appendChild(fix);
           })();
           })();
         })(doc);
         })(doc);

Navigation menu