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