diff options
author | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-17 00:53:30 +0000 |
---|---|---|
committer | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-17 00:53:30 +0000 |
commit | 50c851f30264d9a7ee512926e2b4b8c5b06dd892 (patch) | |
tree | 3c91ac4456c70fb644714d1b8699d2e6c04f4109 | |
parent | fa90644dcd8945384c8766741f2863d85aa8c6bd (diff) | |
download | chromium_src-50c851f30264d9a7ee512926e2b4b8c5b06dd892.zip chromium_src-50c851f30264d9a7ee512926e2b4b8c5b06dd892.tar.gz chromium_src-50c851f30264d9a7ee512926e2b4b8c5b06dd892.tar.bz2 |
Implement overlay.
BUG=
TEST=
Review URL: http://codereview.chromium.org/6334067
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75215 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/resources/gpu_internals/overlay.css | 37 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals/overlay.js | 176 | ||||
-rw-r--r-- | chrome/browser/resources/gpu_internals/overlay_test.html | 51 |
3 files changed, 264 insertions, 0 deletions
diff --git a/chrome/browser/resources/gpu_internals/overlay.css b/chrome/browser/resources/gpu_internals/overlay.css new file mode 100644 index 0000000..994b527 --- /dev/null +++ b/chrome/browser/resources/gpu_internals/overlay.css @@ -0,0 +1,37 @@ +/* +Copyright (c) 2011 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. +*/ +.overlay-root { + display: -webkit-box; + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + background: rgba(0, 0, 0, 0.8); + -webkit-user-select: none; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + -webkit-box-pack: center; + z-index: 1000; +} + +.overlay-root:not([visible]), +.overlay:not([visible]) +{ + display: none; +} + +.overlay-root > .content-host { + -webkit-user-select: auto; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + -webkit-box-pack: center; +} + +.overlay-root > .content-host > * { + background: rgb(255, 255, 255); +} diff --git a/chrome/browser/resources/gpu_internals/overlay.js b/chrome/browser/resources/gpu_internals/overlay.js new file mode 100644 index 0000000..9a87d7d --- /dev/null +++ b/chrome/browser/resources/gpu_internals/overlay.js @@ -0,0 +1,176 @@ +// Copyright (c) 2011 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 Implements an element that is hidden by default, but + * when shown, dims and (attempts to) disable the main document. + * + * You can turn any div into an overlay. Note that while an + * overlay element is shown, its parent is changed. Hiding the overlay + * restores its original parentage. + * + */ +cr.define('gpu', function() { + /** + * Manages a full-window div that darkens the window, disables + * input, and hosts the currently-visible overlays. You shouldn't + * have to instantiate this directly --- it gets set automatically. + * @param {Object=} opt_propertyBag Optional properties. + * @constructor + * @extends {HTMLDivElement} + */ + var OverlayRoot = cr.ui.define('div'); + OverlayRoot.prototype = { + __proto__ : HTMLDivElement.prototype, + decorate: function() { + this.classList.add('overlay-root'); + this.visible = false; + + this.contentHost = this.ownerDocument.createElement('div'); + this.contentHost.classList.add('content-host'); + + this.tabCatcher = this.ownerDocument.createElement('span'); + this.tabCatcher.tabIndex = 0; + + this.appendChild(this.contentHost); + + this.onKeydownBoundToThis_ = this.onKeydown_.bind(this); + this.onFocusInBoundToThis_ = this.onFocusIn_.bind(this); + this.addEventListener('mousedown', this.onMousedown_.bind(this)); + }, + + /** + * Adds an overlay, attaching it to the contentHost so that it is visible. + */ + showOverlay: function(overlay) { + // Reparent this to the overlay content host. + overlay.oldParent_ = overlay.parentNode; + this.contentHost.appendChild(overlay); + this.contentHost.appendChild(this.tabCatcher); + + // Show the overlay root. + this.ownerDocument.body.classList.add('disabled-by-overlay'); + this.visible = true; + + // Bring overlay into focus. + overlay.tabIndex = 0; + overlay.focus(); + + // Listen to key and focus events to prevent focus from + // leaving the overlay. + this.ownerDocument.addEventListener('focusin', + this.onFocusInBoundToThis_, true); + overlay.addEventListener('keydown', this.onKeydownBoundToThis_); + }, + + /** + * Clicking outside of the overlay will de-focus the overlay. The + * next tab will look at the entire document to determine the focus. + * For certain documents, this can cause focus to "leak" outside of + * the overlay. + */ + onMousedown_: function(e) { + if (e.target == this) { + e.preventDefault(); + } + }, + + /** + * Prevents forward-tabbing out of the overlay + */ + onFocusIn_: function(e) { + if (e.target == this.tabCatcher) { + window.setTimeout(this.focusOverlay_.bind(this), 0); + } + }, + + focusOverlay_: function() { + this.contentHost.firstChild.focus(); + }, + + /** + * Prevent the user from shift-tabbing backwards out of the overlay. + */ + onKeydown_: function(e) { + if (e.keyCode == 9 && + e.shiftKey && + e.target == this.contentHost.firstChild) { + e.preventDefault(); + } + }, + + /** + * Hides an overlay, attaching it to its original parent if needed. + */ + hideOverlay: function(overlay) { + // hide the overlay root + this.visible = false; + this.ownerDocument.body.classList.remove('disabled-by-overlay'); + this.lastFocusOut_ = undefined; + + // put the overlay back on its previous parent + overlay.parentNode.removeChild(this.tabCatcher); + if (overlay.oldParent_) { + overlay.oldParent_.appendChild(overlay); + delete overlay.oldParent_; + } else { + this.contentHost.removeChild(overlay); + } + + // remove listeners + overlay.removeEventListener('keydown', this.onKeydownBoundToThis_); + this.ownerDocument.removeEventListener('focusin', + this.onFocusInBoundToThis_); + } + }; + + cr.defineProperty(OverlayRoot, 'visible', cr.PropertyKind.BOOL_ATTR); + + /** + * Creates a new overlay element. It will not be visible until shown. + * @param {Object=} opt_propertyBag Optional properties. + * @constructor + * @extends {HTMLDivElement} + */ + var Overlay = cr.ui.define('div'); + + Overlay.prototype = { + __proto__ : HTMLDivElement.prototype, + + /** + * Initializes the overlay element. + */ + decorate: function() { + // create the overlay root on this document if its not present + if (!this.ownerDocument.querySelector('.overlay-root')) { + var overlayRoot = this.ownerDocument.createElement('div'); + cr.ui.decorate(overlayRoot, OverlayRoot); + this.ownerDocument.body.appendChild(overlayRoot); + } + + this.classList.add('overlay'); + this.visible = false; + }, + + onVisibleChanged_: function() { + var overlayRoot = this.ownerDocument.querySelector('.overlay-root'); + if (this.visible) { + overlayRoot.showOverlay(this); + } else { + overlayRoot.hideOverlay(this); + } + } + }; + + /** + * Shows and hides the overlay. Note that while visible == true, the overlay + * element will be tempoarily reparented to another place in the DOM. + */ + cr.defineProperty(Overlay, 'visible', cr.PropertyKind.BOOL_ATTR, + Overlay.prototype.onVisibleChanged_); + + return { + Overlay : Overlay + }; +});
\ No newline at end of file diff --git a/chrome/browser/resources/gpu_internals/overlay_test.html b/chrome/browser/resources/gpu_internals/overlay_test.html new file mode 100644 index 0000000..34de09c --- /dev/null +++ b/chrome/browser/resources/gpu_internals/overlay_test.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html> +<head> +<title></title> +<link rel="stylesheet" href="overlay.css"> +<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script> +<script src="../shared/js/cr.js"></script> +<script src="../shared/js/cr/ui.js"></script> +<script src="overlay.js"></script> +<script> + +goog.require('goog.testing.jsunit'); + +</script> + +</head> +<body> +<div id="sandbox"></div> +<script> + +var sandbox = document.getElementById('sandbox'); +var overlay; + +function testShowHideUnparented() { + overlay = new gpu.Overlay(); + overlay.innerHTML = + '<h3>Hello</h3>B1:<button>foo</button></p>B2:<button>blah</button>'; + overlay.visible = true; + assertNotEquals(overlay.parentNode, null); + + overlay.visible = false; + assertEquals(overlay.parentNode, null); +} + +function testShowHideParented() { + overlay = new gpu.Overlay(); + overlay.innerHTML = + '<h3>Hello</h3>B1:<button>foo</button></p>B2:<button>blah</button>'; + document.body.appendChild(overlay); + overlay.visible = true; + assertNotEquals(overlay.parentNode, null); + + overlay.visible = false; + assertEquals(overlay.parentNode, document.body); +} + +</script> + +</body> +</html> + |