// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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() {
var overlays = document.querySelectorAll('.overlay:not([hidden])');
return overlays[overlays.length - 1];
}
/**
* Makes initializations which must hook at the document level.
*/
function globalInitialization() {
// Listen to focus events and make sure focus doesn't move outside of a
// visible overlay .page.
document.addEventListener('focus', function(e) {
var overlay = getTopOverlay();
var page = overlay ? overlay.querySelector('.page:not([hidden])') : null;
if (!page || page.contains(e.target))
return;
var focusElement = page.querySelector('button, input, list, select, a');
if (focusElement)
focusElement.focus();
}, true);
// Close the overlay on escape.
document.addEventListener('keydown', function(e) {
if (e.keyCode == 27) { // Escape
var overlay = getTopOverlay();
if (!overlay)
return;
cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
}
});
window.addEventListener('resize', setMaxHeightAllPages);
setMaxHeightAllPages();
}
/**
* Sets the max-height of all pages in all overlays, based on the window
* height.
*/
function setMaxHeightAllPages() {
var pages = document.querySelectorAll('.overlay .page');
var maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';
for (var i = 0; i < pages.length; i++)
pages[i].style.maxHeight = maxHeight;
}
/**
* Adds behavioral hooks for the given overlay.
* @param {HTMLElement} overlay The .overlay.
*/
function setupOverlay(overlay) {
// Close the overlay on clicking any of the pages' close buttons.
var closeButtons = overlay.querySelectorAll('.page > .close-button');
for (var i = 0; i < closeButtons.length; i++) {
closeButtons[i].addEventListener('click', function(e) {
cr.dispatchSimpleEvent(overlay, 'cancelOverlay');
});
}
// Remove the 'pulse' animation any time the overlay is hidden or shown.
overlay.__defineSetter__('hidden', function(value) {
this.classList.remove('pulse');
if (value)
this.setAttribute('hidden', true);
else
this.removeAttribute('hidden');
});
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.
var overlayPage = this.querySelector('.page:not([hidden])');
if (overlayPage)
overlayPage.classList.add('pulse');
});
overlay.addEventListener('webkitAnimationEnd', function(e) {
e.target.classList.remove('pulse');
});
}
return {
globalInitialization: globalInitialization,
setupOverlay: setupOverlay,
};
});
document.addEventListener('DOMContentLoaded',
cr.ui.overlay.globalInitialization);