1010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// Use of this source code is governed by a BSD-style license that can be
3010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis// found in the LICENSE file.
4010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
5010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis/**
6010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis * @fileoverview Provides dialog-like behaviors for the tracing UI.
7010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis */
8010583560e0e6db74fe50b840bce46ba6537de63Jamie Genniscr.define('cr.ui.overlay', function() {
9010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
10010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  /**
11010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * Gets the top, visible overlay. It makes the assumption that if multiple
12010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * overlays are visible, the last in the byte order is topmost.
13010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * TODO(estade): rely on aria-visibility instead?
14010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * @return {HTMLElement} The overlay.
15010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   */
16010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  function getTopOverlay() {
17010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    var overlays = document.querySelectorAll('.overlay:not([hidden])');
18010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    return overlays[overlays.length - 1];
19010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  }
20010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
21010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  /**
22010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * Makes initializations which must hook at the document level.
23010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   */
24010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  function globalInitialization() {
25010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // Listen to focus events and make sure focus doesn't move outside of a
26010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // visible overlay .page.
27010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    document.addEventListener('focus', function(e) {
28010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      var overlay = getTopOverlay();
29010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      var page = overlay ? overlay.querySelector('.page:not([hidden])') : null;
30010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (!page || page.contains(e.target))
31010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        return;
32010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
33010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      var focusElement = page.querySelector('button, input, list, select, a');
34010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (focusElement)
35010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        focusElement.focus();
36010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    }, true);
37010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
38010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // Close the overlay on escape.
39010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    document.addEventListener('keydown', function(e) {
40010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (e.keyCode == 27) {  // Escape
41010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        var overlay = getTopOverlay();
42010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        if (!overlay)
43010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis          return;
44010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
45010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
46010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      }
47010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    });
48010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
49010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    window.addEventListener('resize', setMaxHeightAllPages);
50010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
51010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    setMaxHeightAllPages();
52010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  }
53010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
54010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  /**
55010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * Sets the max-height of all pages in all overlays, based on the window
56010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * height.
57010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   */
58010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  function setMaxHeightAllPages() {
59010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    var pages = document.querySelectorAll('.overlay .page');
60010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
61010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    var maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';
62010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    for (var i = 0; i < pages.length; i++)
63010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      pages[i].style.maxHeight = maxHeight;
64010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  }
65010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
66010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  /**
67010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * Adds behavioral hooks for the given overlay.
68010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   * @param {HTMLElement} overlay The .overlay.
69010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis   */
70010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  function setupOverlay(overlay) {
71010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // Close the overlay on clicking any of the pages' close buttons.
72010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    var closeButtons = overlay.querySelectorAll('.page > .close-button');
73010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    for (var i = 0; i < closeButtons.length; i++) {
74010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      closeButtons[i].addEventListener('click', function(e) {
75010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
76010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      });
77010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    }
78010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
79010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // Remove the 'pulse' animation any time the overlay is hidden or shown.
80010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    overlay.__defineSetter__('hidden', function(value) {
81010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      this.classList.remove('pulse');
82010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (value)
83010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        this.setAttribute('hidden', true);
84010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      else
85010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        this.removeAttribute('hidden');
86010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    });
87010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    overlay.__defineGetter__('hidden', function() {
88010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      return this.hasAttribute('hidden');
89010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    });
90010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
91010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    // Shake when the user clicks away.
92010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    overlay.addEventListener('click', function(e) {
93010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      // Only pulse if the overlay was the target of the click.
94010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (this != e.target)
95010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        return;
96010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
97010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      // This may be null while the overlay is closing.
98010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      var overlayPage = this.querySelector('.page:not([hidden])');
99010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      if (overlayPage)
100010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis        overlayPage.classList.add('pulse');
101010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    });
102010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    overlay.addEventListener('webkitAnimationEnd', function(e) {
103010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis      e.target.classList.remove('pulse');
104010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    });
105010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  }
106010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
107010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  return {
108010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    globalInitialization: globalInitialization,
109010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis    setupOverlay: setupOverlay,
110010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis  };
111010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis});
112010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis
113010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennisdocument.addEventListener('DOMContentLoaded',
114010583560e0e6db74fe50b840bce46ba6537de63Jamie Gennis                          cr.ui.overlay.globalInitialization);
115