summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 00:53:30 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 00:53:30 +0000
commit50c851f30264d9a7ee512926e2b4b8c5b06dd892 (patch)
tree3c91ac4456c70fb644714d1b8699d2e6c04f4109
parentfa90644dcd8945384c8766741f2863d85aa8c6bd (diff)
downloadchromium_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.css37
-rw-r--r--chrome/browser/resources/gpu_internals/overlay.js176
-rw-r--r--chrome/browser/resources/gpu_internals/overlay_test.html51
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>
+