Global Metrics

path: .metrics.halstead.difficulty
old: 50.61818181818182
new: 50.88181818181818

path: .metrics.halstead.level
old: 0.019755747126436785
new: 0.01965338574236198

path: .metrics.halstead.purity_ratio
old: 0.810700058485081
new: 0.80927025238546

path: .metrics.halstead.effort
old: 183139.19681889264
new: 184418.2995351907

path: .metrics.halstead.time
old: 10174.399823271811
new: 10245.46108528837

path: .metrics.halstead.bugs
old: 1.074978096879278
new: 1.0799776156202774

path: .metrics.halstead.volume
old: 3618.0516612927786
new: 3624.4439787155575

path: .metrics.halstead.length
old: 566.0
new: 567.0

path: .metrics.halstead.N2
old: 192.0
new: 193.0

path: .metrics.mi.mi_sei
old: -0.4713423384307162
new: -0.4845850854045324

path: .metrics.mi.mi_visual_studio
old: 19.9442632723902
new: 19.93889533512251

path: .metrics.mi.mi_original
old: 34.10469019578724
new: 34.09551102305949

Spaces Data

Minimal test - lines (187, 206)

path: .spaces[0].spaces[8].metrics.mi.mi_sei
old: 75.79491239458198
new: 75.67859976683403

path: .spaces[0].spaces[8].metrics.mi.mi_original
old: 92.88899652724022
new: 92.8083747572532

path: .spaces[0].spaces[8].metrics.mi.mi_visual_studio
old: 54.32105060072527
new: 54.27390336681473

path: .spaces[0].spaces[8].metrics.halstead.bugs
old: 0.09125049863430952
new: 0.095779645193487

path: .spaces[0].spaces[8].metrics.halstead.N2
old: 17.0
new: 18.0

path: .spaces[0].spaces[8].metrics.halstead.purity_ratio
old: 0.5707707033278251
new: 0.56198961558432

path: .spaces[0].spaces[8].metrics.halstead.volume
old: 236.8281419610299
new: 240.528581679171

path: .spaces[0].spaces[8].metrics.halstead.difficulty
old: 19.125
new: 20.25

path: .spaces[0].spaces[8].metrics.halstead.level
old: 0.05228758169934641
new: 0.04938271604938271

path: .spaces[0].spaces[8].metrics.halstead.length
old: 64.0
new: 65.0

path: .spaces[0].spaces[8].metrics.halstead.effort
old: 4529.338215004696
new: 4870.703779003213

path: .spaces[0].spaces[8].metrics.halstead.time
old: 251.62990083359423
new: 270.5946543890674

Code

    update(data = {}) {
      if (data.sheetCount) {
        if (this.sheetCount !== data.sheetCount || this.currentSheet !== 1) {
          // when sheet count changes, scroll position will get reset
          this.currentSheet = 1;
        }
        this.sheetCount = data.sheetCount;
      }
      if (data.currentPage) {
        this.currentSheet = data.currentPage;
      }
      document.l10n.setAttributes(
        this.elements.sheetIndicator,
        this.elements.sheetIndicator.dataset.l10nId,
        {
          sheetNum: this.currentSheet,
          sheetCount: this.sheetCount,
        }
      );
    }

Minimal test - lines (12, 207)

path: .spaces[0].metrics.mi.mi_original
old: 35.3718481404688
new: 35.36258722973962

path: .spaces[0].metrics.mi.mi_visual_studio
old: 20.685291310215675
new: 20.679875572947143

path: .spaces[0].metrics.mi.mi_sei
old: -1.8861527727230791
new: -1.89951344270618

path: .spaces[0].metrics.halstead.length
old: 561.0
new: 562.0

path: .spaces[0].metrics.halstead.level
old: 0.019237749546279492
new: 0.01913702834446651

path: .spaces[0].metrics.halstead.bugs
old: 1.083788211340486
new: 1.0888797046229632

path: .spaces[0].metrics.halstead.volume
old: 3566.586674590745
new: 3572.944226595363

path: .spaces[0].metrics.halstead.purity_ratio
old: 0.7922660123895706
new: 0.7908562863888774

path: .spaces[0].metrics.halstead.difficulty
old: 51.9811320754717
new: 52.25471698113208

path: .spaces[0].metrics.halstead.time
old: 10299.734055028828
new: 10372.399408339474

path: .spaces[0].metrics.halstead.N2
old: 190.0
new: 191.0

path: .spaces[0].metrics.halstead.effort
old: 185395.21299051892
new: 186703.18935011057

Code

  class PrintPreviewPagination extends HTMLElement {
    static get markup() {
      return `
      
      
        
        
        
        
        
      
      `;
    }

    static get defaultProperties() {
      return {
        currentPage: 1,
        sheetCount: 1,
      };
    }

    get previewBrowser() {
      if (!this._previewBrowser) {
        // Assuming we're a sibling of our preview browser.
        this._previewBrowser = this.parentNode.querySelector(
          ".printPreviewBrowser"
        );
      }
      return this._previewBrowser;
    }

    set previewBrowser(aBrowser) {
      this._previewBrowser = aBrowser;
    }

    connectedCallback() {
      MozXULElement.insertFTLIfNeeded("toolkit/printing/printPreview.ftl");

      const shadowRoot = this.attachShadow({ mode: "open" });
      document.l10n.connectRoot(shadowRoot);

      let fragment = MozXULElement.parseXULToFragment(this.constructor.markup);
      this.shadowRoot.append(fragment);

      this.elements = {
        sheetIndicator: shadowRoot.querySelector("#sheetIndicator"),
        homeButton: shadowRoot.querySelector("#navigateHome"),
        previousButton: shadowRoot.querySelector("#navigatePrevious"),
        nextButton: shadowRoot.querySelector("#navigateNext"),
        endButton: shadowRoot.querySelector("#navigateEnd"),
      };

      this.shadowRoot.addEventListener("click", this);

      let knownAttrs = {
        "sheet-count": "sheetCount",
        "current-page": "currentPage",
      };
      this.mutationObserver = new MutationObserver(changes => {
        let opts = {};
        for (let change of changes) {
          let { attributeName, target, type } = change;
          if (type == "attributes" && attributeName in knownAttrs) {
            opts[knownAttrs[attributeName]] = parseInt(
              target.getAttribute(attributeName),
              10
            );
          }
        }
        if (opts.sheetCount || opts.currentPage) {
          this.update(opts);
        }
      });
      this.mutationObserver.observe(this.previewBrowser, {
        attributes: ["current-page", "sheet-count"],
      });

      this.currentPreviewBrowserObserver = new MutationObserver(changes => {
        for (let change of changes) {
          if (change.attributeName == "previewtype") {
            let previewType = change.target.getAttribute("previewtype");
            this.previewBrowser = change.target.querySelector(
              `browser[previewtype="${previewType}"]`
            );
            this.mutationObserver.disconnect();
            this.mutationObserver.observe(this.previewBrowser, {
              attributes: ["current-page", "sheet-count"],
            });
          }
        }
      });
      this.currentPreviewBrowserObserver.observe(this.parentNode, {
        attributes: ["previewtype"],
      });

      // Initial render with some default values
      // We'll be updated with real values when available
      this.update(this.constructor.defaultProperties);
    }

    disconnectedCallback() {
      document.l10n.disconnectRoot(this.shadowRoot);
      this.shadowRoot.textContent = "";
      this.mutationObserver?.disconnect();
      delete this.mutationObserver;
      this.currentPreviewBrowserObserver?.disconnect();
      delete this.currentPreviewBrowserObserver;
    }

    handleEvent(event) {
      if (event.type == "click" && event.button != 0) {
        return;
      }
      event.stopPropagation();

      switch (event.target) {
        case this.elements.homeButton:
          this.navigate(0, 0, "home");
          break;
        case this.elements.previousButton:
          this.navigate(-1, 0, 0);
          break;
        case this.elements.nextButton:
          this.navigate(1, 0, 0);
          break;
        case this.elements.endButton:
          this.navigate(0, 0, "end");
          break;
      }
    }

    navigate(aDirection, aPageNum, aHomeOrEnd) {
      const nsIWebBrowserPrint = Ci.nsIWebBrowserPrint;
      let targetNum;
      let navType;
      // we use only one of aHomeOrEnd, aDirection, or aPageNum
      if (aHomeOrEnd) {
        // We're going to either the very first page ("home"), or the
        // very last page ("end").
        if (aHomeOrEnd == "home") {
          targetNum = 1;
          navType = nsIWebBrowserPrint.PRINTPREVIEW_HOME;
        } else {
          targetNum = this.sheetCount;
          navType = nsIWebBrowserPrint.PRINTPREVIEW_END;
        }
      } else if (aPageNum) {
        // We're going to a specific page (aPageNum)
        targetNum = Math.min(Math.max(1, aPageNum), this.sheetCount);
        navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
      } else {
        // aDirection is either +1 or -1, and allows us to increment
        // or decrement our currently viewed page.
        targetNum = Math.min(
          Math.max(1, this.currentSheet + aDirection),
          this.sheetCount
        );
        navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
      }

      // Preemptively update our own state, rather than waiting for the message from the child process
      // This allows subsequent clicks of next/back to advance 1 page per click if possible
      // and keeps the UI feeling more responsive
      this.update({ currentPage: targetNum });

      this.previewBrowser.sendMessageToActor(
        "Printing:Preview:Navigate",
        {
          navType,
          pageNum: targetNum,
        },
        "Printing"
      );
    }

    update(data = {}) {
      if (data.sheetCount) {
        if (this.sheetCount !== data.sheetCount || this.currentSheet !== 1) {
          // when sheet count changes, scroll position will get reset
          this.currentSheet = 1;
        }
        this.sheetCount = data.sheetCount;
      }
      if (data.currentPage) {
        this.currentSheet = data.currentPage;
      }
      document.l10n.setAttributes(
        this.elements.sheetIndicator,
        this.elements.sheetIndicator.dataset.l10nId,
        {
          sheetNum: this.currentSheet,
          sheetCount: this.sheetCount,
        }
      );
    }
  }