initFeatures(report) {
    this.json = report;

    this._setupMediaQueryListeners();
    this._dropDown.setup(this.onDropDownMenuClick);
    this._setupThirdPartyFilter();
    this._setupElementScreenshotOverlay(this._dom.find('.lh-container', this._document));
    this._setUpCollapseDetailsAfterPrinting();
    this._resetUIState();
    this._document.addEventListener('keyup', this.onKeyUp);
    this._document.addEventListener('copy', this.onCopy);

    const topbarLogo = this._dom.find('.lh-topbar__logo', this._document);
    topbarLogo.addEventListener('click', () => this._toggleDarkTheme());

    let turnOffTheLights = false;
    // Do not query the system preferences for DevTools - DevTools should only apply dark theme
    // if dark is selected in the settings panel.
    if (!this._dom.isDevTools() && window.matchMedia('(prefers-color-scheme: dark)').matches) {
      turnOffTheLights = true;
    }

    // Fireworks!
    // To get fireworks you need 100 scores in all core categories, except PWA (because going the PWA route is discretionary).
    const fireworksRequiredCategoryIds = ['performance', 'accessibility', 'best-practices', 'seo'];
    const scoresAll100 = fireworksRequiredCategoryIds.every(id => {
      const cat = report.categories[id];
      return cat && cat.score === 1;
    });
    if (scoresAll100) {
      turnOffTheLights = true;
      this._enableFireworks();
    }

    if (turnOffTheLights) {
      this._toggleDarkTheme(true);
    }

    // There is only a sticky header when at least 2 categories are present.
    if (Object.keys(this.json.categories).length >= 2) {
      this._setupStickyHeaderElements();
      const containerEl = this._dom.find('.lh-container', this._document);
      const elToAddScrollListener = this._getScrollParent(containerEl);
      elToAddScrollListener.addEventListener('scroll', this._updateStickyHeaderOnScroll);

      // Use ResizeObserver where available.
      // TODO: there is an issue with incorrect position numbers and, as a result, performance
      // issues due to layout thrashing.
      // See https://github.com/GoogleChrome/lighthouse/pull/9023/files#r288822287 for details.
      // For now, limit to DevTools.
      if (this._dom.isDevTools()) {
        const resizeObserver = new window.ResizeObserver(this._updateStickyHeaderOnScroll);
        resizeObserver.observe(containerEl);
      } else {
        window.addEventListener('resize', this._updateStickyHeaderOnScroll);
      }
    }

    // Show the metric descriptions by default when there is an error.
    const hasMetricError = report.categories.performance && report.categories.performance.auditRefs
      .some(audit => Boolean(audit.group === 'metrics' && report.audits[audit.id].errorMessage));
    if (hasMetricError) {
      const toggleInputEl = this._dom.find('input.lh-metrics-toggle__input', this._document);
      toggleInputEl.checked = true;
    }

    const showTreemapApp =
      this.json.audits['script-treemap-data'] && this.json.audits['script-treemap-data'].details;
    if (showTreemapApp) {
      this.addButton({
        text: Util.i18n.strings.viewTreemapLabel,
        icon: 'treemap',
        onClick: () => ReportUIFeatures.openTreemap(this.json),
      });
    }

    // Fill in all i18n data.
    for (const node of this._dom.findAll('[data-i18n]', this._dom.document())) {
      // These strings are guaranteed to (at least) have a default English string in Util.UIStrings,
      // so this cannot be undefined as long as `report-ui-features.data-i18n` test passes.
      const i18nAttr = /** @type {keyof LH.I18NRendererStrings} */ (node.getAttribute('data-i18n'));
      node.textContent = Util.i18n.strings[i18nAttr];
    }
  }
/**
   * Adds tools button, print, and other functionality to the report. The method
   * should be called whenever the report needs to be re-rendered.
   * @param {LH.Result} report
   */
Adds tools button, print, and other functionality to the report. The method
should be called whenever the report needs to be re-rendered.
Adds tools button print and other functionality to the report . The method should be called whenever the report needs to be re - rendered .
initFeatures(report) {
    this.json = report;
    this._setupMediaQueryListeners();
    this._dropDown.setup(this.onDropDownMenuClick);
    this._setupThirdPartyFilter();
    this._setupElementScreenshotOverlay(this._dom.find('.lh-container', this._document));
    this._setUpCollapseDetailsAfterPrinting();
    this._resetUIState();
    this._document.addEventListener('keyup', this.onKeyUp);
    this._document.addEventListener('copy', this.onCopy);
    const topbarLogo = this._dom.find('.lh-topbar__logo', this._document);
    topbarLogo.addEventListener('click', () => this._toggleDarkTheme());
    let turnOffTheLights = false;
    if (!this._dom.isDevTools() && window.matchMedia('(prefers-color-scheme: dark)').matches) {
      turnOffTheLights = true;
    }
    const fireworksRequiredCategoryIds = ['performance', 'accessibility', 'best-practices', 'seo'];
    const scoresAll100 = fireworksRequiredCategoryIds.every(id => {
      const cat = report.categories[id];
      return cat && cat.score === 1;
    });
    if (scoresAll100) {
      turnOffTheLights = true;
      this._enableFireworks();
    }
    if (turnOffTheLights) {
      this._toggleDarkTheme(true);
    }
    if (Object.keys(this.json.categories).length >= 2) {
      this._setupStickyHeaderElements();
      const containerEl = this._dom.find('.lh-container', this._document);
      const elToAddScrollListener = this._getScrollParent(containerEl);
      elToAddScrollListener.addEventListener('scroll', this._updateStickyHeaderOnScroll);
      if (this._dom.isDevTools()) {
        const resizeObserver = new window.ResizeObserver(this._updateStickyHeaderOnScroll);
        resizeObserver.observe(containerEl);
      } else {
        window.addEventListener('resize', this._updateStickyHeaderOnScroll);
      }
    }
    const hasMetricError = report.categories.performance && report.categories.performance.auditRefs
      .some(audit => Boolean(audit.group === 'metrics' && report.audits[audit.id].errorMessage));
    if (hasMetricError) {
      const toggleInputEl = this._dom.find('input.lh-metrics-toggle__input', this._document);
      toggleInputEl.checked = true;
    }
    const showTreemapApp =
      this.json.audits['script-treemap-data'] && this.json.audits['script-treemap-data'].details;
    if (showTreemapApp) {
      this.addButton({
        text: Util.i18n.strings.viewTreemapLabel,
        icon: 'treemap',
        onClick: () => ReportUIFeatures.openTreemap(this.json),
      });
    }
    for (const node of this._dom.findAll('[data-i18n]', this._dom.document())) {
      const i18nAttr =  (node.getAttribute('data-i18n'));
      node.textContent = Util.i18n.strings[i18nAttr];
    }
  }
initFeatures ( report ) { this . json = report ; this . _setupMediaQueryListeners ( ) ; this . _dropDown . setup ( this . onDropDownMenuClick ) ; this . _setupThirdPartyFilter ( ) ; this . _setupElementScreenshotOverlay ( this . _dom . find ( '.lh-container' , this . _document ) ) ; this . _setUpCollapseDetailsAfterPrinting ( ) ; this . _resetUIState ( ) ; this . _document . addEventListener ( 'keyup' , this . onKeyUp ) ; this . _document . addEventListener ( 'copy' , this . onCopy ) ; const topbarLogo = this . _dom . find ( '.lh-topbar__logo' , this . _document ) ; topbarLogo . addEventListener ( 'click' , ( ) => this . _toggleDarkTheme ( ) ) ; let turnOffTheLights = false ; if ( ! this . _dom . isDevTools ( ) && window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ) { turnOffTheLights = true ; } const fireworksRequiredCategoryIds = [ 'performance' , 'accessibility' , 'best-practices' , 'seo' ] ; const scoresAll100 = fireworksRequiredCategoryIds . every ( id => { const cat = report . categories [ id ] ; return cat && cat . score === 1 ; } ) ; if ( scoresAll100 ) { turnOffTheLights = true ; this . _enableFireworks ( ) ; } if ( turnOffTheLights ) { this . _toggleDarkTheme ( true ) ; } if ( Object . keys ( this . json . categories ) . length >= 2 ) { this . _setupStickyHeaderElements ( ) ; const containerEl = this . _dom . find ( '.lh-container' , this . _document ) ; const elToAddScrollListener = this . _getScrollParent ( containerEl ) ; elToAddScrollListener . addEventListener ( 'scroll' , this . _updateStickyHeaderOnScroll ) ; if ( this . _dom . isDevTools ( ) ) { const resizeObserver = new window . ResizeObserver ( this . _updateStickyHeaderOnScroll ) ; resizeObserver . observe ( containerEl ) ; } else { window . addEventListener ( 'resize' , this . _updateStickyHeaderOnScroll ) ; } } const hasMetricError = report . categories . performance && report . categories . performance . auditRefs . some ( audit => Boolean ( audit . group === 'metrics' && report . audits [ audit . id ] . errorMessage ) ) ; if ( hasMetricError ) { const toggleInputEl = this . _dom . find ( 'input.lh-metrics-toggle__input' , this . _document ) ; toggleInputEl . checked = true ; } const showTreemapApp = this . json . audits [ 'script-treemap-data' ] && this . json . audits [ 'script-treemap-data' ] . details ; if ( showTreemapApp ) { this . addButton ( { text : Util . i18n . strings . viewTreemapLabel , icon : 'treemap' , onClick : ( ) => ReportUIFeatures . openTreemap ( this . json ) , } ) ; } for ( const node of this . _dom . findAll ( '[data-i18n]' , this . _dom . document ( ) ) ) { const i18nAttr = ( node . getAttribute ( 'data-i18n' ) ) ; node . textContent = Util . i18n . strings [ i18nAttr ] ; } }
Adds tools button, print, and other functionality to the report.
Adds tools button print and other functionality to the report .
// Do not query the system preferences for DevTools - DevTools should only apply dark theme // if dark is selected in the settings panel. // Fireworks! // To get fireworks you need 100 scores in all core categories, except PWA (because going the PWA route is discretionary). // There is only a sticky header when at least 2 categories are present. // Use ResizeObserver where available. // TODO: there is an issue with incorrect position numbers and, as a result, performance // issues due to layout thrashing. // See https://github.com/GoogleChrome/lighthouse/pull/9023/files#r288822287 for details. // For now, limit to DevTools. // Show the metric descriptions by default when there is an error. // Fill in all i18n data. // These strings are guaranteed to (at least) have a default English string in Util.UIStrings, // so this cannot be undefined as long as `report-ui-features.data-i18n` test passes. /** @type {keyof LH.I18NRendererStrings} */