File: overlay.js

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (158 lines) | stat: -rw-r--r-- 5,185 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Provides dialog-like behaviors for the tracing UI.
 */
cr.define('cr.ui.overlay', function() {
  /**
   * Gets the top, visible overlay. It makes the assumption that if multiple
   * overlays are visible, the last in the byte order is topmost.
   * TODO(estade): rely on aria-visibility instead?
   * @return {HTMLElement} The overlay.
   */
  function getTopOverlay() {
    const overlays = /** @type !NodeList<!HTMLElement> */ (
        document.querySelectorAll('.overlay:not([hidden])'));
    return overlays[overlays.length - 1];
  }

  /**
   * Returns a visible default button of the overlay, if it has one. If the
   * overlay has more than one, the first one will be returned.
   *
   * @param {HTMLElement} overlay The .overlay.
   * @return {HTMLElement} The default button.
   */
  function getDefaultButton(overlay) {
    function isHidden(node) {
      return node.hidden;
    }
    const defaultButtons = /** @type !NodeList<!HTMLElement> */ (
        overlay.querySelectorAll('.page .button-strip > .default-button'));
    for (let i = 0; i < defaultButtons.length; i++) {
      if (!findAncestor(defaultButtons[i], isHidden)) {
        return defaultButtons[i];
      }
    }
    return null;
  }

  /** @type {boolean} */
  let globallyInitialized = false;

  /**
   * Makes initializations which must hook at the document level.
   */
  function globalInitialization() {
    if (!globallyInitialized) {
      document.addEventListener('keydown', function(e) {
        const overlay = getTopOverlay();
        if (!overlay) {
          return;
        }

        // Close the overlay on escape.
        if (e.key === 'Escape') {
          cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
        }

        // Execute the overlay's default button on enter, unless focus is on an
        // element that has standard behavior for the enter key.
        const forbiddenTagNames = /^(A|BUTTON|SELECT|TEXTAREA)$/;
        if (e.key === 'Enter' &&
            !forbiddenTagNames.test(document.activeElement.tagName)) {
          const button = getDefaultButton(overlay);
          if (button) {
            button.click();
            // Executing the default button may result in focus moving to a
            // different button. Calling preventDefault is necessary to not have
            // that button execute as well.
            e.preventDefault();
          }
        }
      });

      window.addEventListener('resize', setMaxHeightAllPages);
      globallyInitialized = true;
    }

    setMaxHeightAllPages();
  }

  /**
   * Sets the max-height of all pages in all overlays, based on the window
   * height.
   */
  function setMaxHeightAllPages() {
    const pages =
        document.querySelectorAll('.overlay .page:not(.not-resizable)');

    const maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';
    for (let i = 0; i < pages.length; i++) {
      pages[i].style.maxHeight = maxHeight;
    }
  }

  /**
   * Adds behavioral hooks for the given overlay.
   * @param {HTMLElement} overlay The .overlay.
   *
   * TODO(crbug.com/41138643): This function makes use of deprecated getter or
   * setter functions.
   * @suppress {deprecated}
   */
  function setupOverlay(overlay) {
    // Close the overlay on clicking any of the pages' close buttons.
    const closeButtons = overlay.querySelectorAll('.page > .close-button');
    for (let i = 0; i < closeButtons.length; i++) {
      closeButtons[i].addEventListener('click', function(e) {
        if (cr.ui.FocusOutlineManager) {
          cr.ui.FocusOutlineManager.forDocument(document).updateVisibility();
        }
        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
      });
    }

    // TODO(crbug.com/41138643): Remove above suppression once we no longer use
    // deprecated functions defineSetter, and defineGetter.
    // Remove the 'pulse' animation any time the overlay is hidden or shown.
    // eslint-disable-next-line no-restricted-properties
    overlay.__defineSetter__('hidden', function(value) {
      this.classList.remove('pulse');
      if (value) {
        this.setAttribute('hidden', true);
      } else {
        this.removeAttribute('hidden');
      }
    });
    // eslint-disable-next-line no-restricted-properties
    overlay.__defineGetter__('hidden', function() {
      return this.hasAttribute('hidden');
    });

    // Shake when the user clicks away.
    overlay.addEventListener('click', function(e) {
      // Only pulse if the overlay was the target of the click.
      if (this !== e.target) {
        return;
      }

      // This may be null while the overlay is closing.
      const overlayPage = this.querySelector('.page:not([hidden])');
      if (overlayPage) {
        overlayPage.classList.add('pulse');
      }
    });
    overlay.addEventListener('animationend', function(e) {
      e.target.classList.remove('pulse');
    });
  }

  return {
    getDefaultButton: getDefaultButton,
    globalInitialization: globalInitialization,
    setupOverlay: setupOverlay,
  };
});