summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/help
diff options
context:
space:
mode:
authorygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-01 16:46:29 +0000
committerygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-01 16:46:29 +0000
commita18a7ebb718206f6242ad81f4446414ba75bc6c2 (patch)
treedf9d08af5dec58efbac423c84105dfd17088d4e3 /chrome/browser/resources/help
parent4a58c42d044631d9ca3e1f80747e3089a8a87c05 (diff)
downloadchromium_src-a18a7ebb718206f6242ad81f4446414ba75bc6c2.zip
chromium_src-a18a7ebb718206f6242ad81f4446414ba75bc6c2.tar.gz
chromium_src-a18a7ebb718206f6242ad81f4446414ba75bc6c2.tar.bz2
Fixed {overlay|focus|scrolling} handling on the help page.
BUG=305736 TEST=manual tests on Linux ChromeOS build. Review URL: https://codereview.chromium.org/50853002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232414 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources/help')
-rw-r--r--chrome/browser/resources/help/channel_change_page.html2
-rw-r--r--chrome/browser/resources/help/channel_change_page.js4
-rw-r--r--chrome/browser/resources/help/help.html4
-rw-r--r--chrome/browser/resources/help/help.js48
-rw-r--r--chrome/browser/resources/help/help_base_page.js245
-rw-r--r--chrome/browser/resources/help/help_focus_manager.js27
6 files changed, 295 insertions, 35 deletions
diff --git a/chrome/browser/resources/help/channel_change_page.html b/chrome/browser/resources/help/channel_change_page.html
index 0b4de9f..d911b2e 100644
--- a/chrome/browser/resources/help/channel_change_page.html
+++ b/chrome/browser/resources/help/channel_change_page.html
@@ -3,7 +3,7 @@
<h1 i18n-content="channelChangePageTitle"></h1>
<div class="content-area">
<div class="channel-change-page-channel">
- <input id="channel-change-page-stable-optiop"
+ <input id="channel-change-page-stable-option"
type="radio" name="channel" value="stable-channel">
<label for="channel-change-page-stable-optiop" i18n-content="stable">
</label>
diff --git a/chrome/browser/resources/help/channel_change_page.js b/chrome/browser/resources/help/channel_change_page.js
index 4f22ce8..1449923 100644
--- a/chrome/browser/resources/help/channel_change_page.js
+++ b/chrome/browser/resources/help/channel_change_page.js
@@ -11,7 +11,7 @@ cr.define('help', function() {
cr.addSingletonGetter(ChannelChangePage);
ChannelChangePage.prototype = {
- __proto__: HTMLDivElement.prototype,
+ __proto__: help.HelpBasePage.prototype,
/**
* Name of the channel the device is currently on.
@@ -50,6 +50,8 @@ cr.define('help', function() {
* Perform initial setup.
*/
initialize: function() {
+ help.HelpBasePage.prototype.initialize.call(this, 'channel-change-page');
+
var self = this;
$('channel-change-page-cancel-button').onclick = function() {
diff --git a/chrome/browser/resources/help/help.html b/chrome/browser/resources/help/help.html
index 045d206..299551a 100644
--- a/chrome/browser/resources/help/help.html
+++ b/chrome/browser/resources/help/help.html
@@ -17,6 +17,8 @@
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/cr/ui.js"></script>
<script src="chrome://resources/js/cr/ui/focus_manager.js"></script>
+ <script src="chrome://help-frame/help_focus_manager.js"></script>
+ <script src="chrome://help-frame/help_base_page.js"></script>
<if expr="pp_ifdef('chromeos')">
<script src="chrome://resources/js/cr/ui/bubble.js"></script>
<script src="chrome://resources/js/cr/ui/overlay.js"></script>
@@ -32,7 +34,7 @@
<include src="channel_change_page.html">
</if>
</div>
- <div class="page">
+ <div id="help-page" class="page">
<header>
<h1 i18n-content="aboutTitle"></h1>
</header>
diff --git a/chrome/browser/resources/help/help.js b/chrome/browser/resources/help/help.js
index b538fc2..d28094d 100644
--- a/chrome/browser/resources/help/help.js
+++ b/chrome/browser/resources/help/help.js
@@ -13,7 +13,7 @@ cr.define('help', function() {
cr.addSingletonGetter(HelpPage);
HelpPage.prototype = {
- __proto__: HTMLDivElement.prototype,
+ __proto__: help.HelpBasePage.prototype,
/**
* True if after update powerwash button should be displayed.
@@ -49,6 +49,8 @@ cr.define('help', function() {
* Perform initial setup.
*/
initialize: function() {
+ help.HelpBasePage.prototype.initialize.call(this, 'help-page');
+
var self = this;
uber.onContentFrameLoaded();
@@ -114,13 +116,16 @@ cr.define('help', function() {
}
if (cr.isChromeOS) {
+ help.ChannelChangePage.getInstance().initialize();
+ this.registerOverlay(help.ChannelChangePage.getInstance());
+
cr.ui.overlay.setupOverlay($('overlay-container'));
cr.ui.overlay.globalInitialization();
$('overlay-container').addEventListener('cancelOverlay', function() {
- self.showOverlay_(null);
+ self.closeOverlay();
});
$('change-channel').onclick = function() {
- self.showOverlay_($('channel-change-page'));
+ self.showOverlay('channel-change-page');
};
var channelChangeDisallowedError = document.createElement('div');
@@ -146,6 +151,7 @@ cr.define('help', function() {
}
cr.ui.FocusManager.disableMouseFocusOnButtons();
+ help.HelpFocusManager.getInstance().initialize();
// Attempt to update.
chrome.send('onPageLoaded');
@@ -217,15 +223,6 @@ cr.define('help', function() {
},
/**
- * Returns current overlay.
- * @return {HTMLElement} Current overlay
- * @private
- */
- getCurrentOverlay_: function() {
- return document.querySelector('#overlay .page.showing');
- },
-
- /**
* @return {boolean} True, if new channel switcher UI is used,
* false otherwise.
* @private
@@ -359,21 +356,6 @@ cr.define('help', function() {
},
/**
- * Sets the given overlay to show. This hides whatever overlay is currently
- * showing, if any.
- * @param {HTMLElement} node The overlay page to show. If null, all
- * overlays are hidden.
- */
- showOverlay_: function(node) {
- var currentlyShowingOverlay = this.getCurrentOverlay_();
- if (currentlyShowingOverlay)
- currentlyShowingOverlay.classList.remove('showing');
- if (node)
- node.classList.add('showing');
- $('overlay-container').hidden = !node;
- },
-
- /**
* Updates name of the current channel, i.e. the name of the
* channel the device is currently on.
* @param {string} channel The name of the current channel
@@ -486,12 +468,16 @@ cr.define('help', function() {
HelpPage.getInstance().setOSFirmware_(firmware);
};
- HelpPage.showOverlay = function(node) {
- HelpPage.getInstance().showOverlay_(node);
+ HelpPage.showOverlay = function(name) {
+ HelpPage.getInstance().showOverlay(name);
};
HelpPage.cancelOverlay = function() {
- HelpPage.getInstance().showOverlay_(null);
+ HelpPage.getInstance().closeOverlay();
+ };
+
+ HelpPage.getTopmostVisiblePage = function() {
+ return HelpPage.getInstance().getTopmostVisiblePage();
};
HelpPage.updateIsEnterpriseManaged = function(isEnterpriseManaged) {
@@ -539,6 +525,4 @@ cr.define('help', function() {
*/
window.onload = function() {
help.HelpPage.getInstance().initialize();
- if (cr.isChromeOS)
- help.ChannelChangePage.getInstance().initialize();
};
diff --git a/chrome/browser/resources/help/help_base_page.js b/chrome/browser/resources/help/help_base_page.js
new file mode 100644
index 0000000..8ebd48e
--- /dev/null
+++ b/chrome/browser/resources/help/help_base_page.js
@@ -0,0 +1,245 @@
+// Copyright 2013 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.
+
+// Helper base class for all help pages and overlays, which controls
+// overlays, focus and scroll. This class is partially based on
+// OptionsPage, but simpler and contains only overlay- and focus-
+// handling logic. As in OptionsPage each page can be an overlay itself,
+// but each page contains its own list of registered overlays which can be
+// displayed over it.
+//
+// TODO (ygorshenin@): crbug.com/313244.
+cr.define('help', function() {
+ function HelpBasePage() {
+ }
+
+ HelpBasePage.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ /**
+ * name of the page, should be the same as an id of the
+ * corresponding HTMLDivElement.
+ */
+ name: null,
+
+ /**
+ * HTML counterpart of this page.
+ */
+ pageDiv: null,
+
+ /**
+ * True if current page is overlay.
+ */
+ isOverlay: false,
+
+ /**
+ * HTMLElement that was last focused when this page was the
+ * topmost.
+ */
+ lastFocusedElement: null,
+
+ /**
+ * State of vertical scrollbars when this page was the topmost.
+ */
+ lastScrollTop: 0,
+
+ /**
+ * Dictionary of registered overlays.
+ */
+ registeredOverlays: {},
+
+ /**
+ * Stores currently focused element.
+ * @private
+ */
+ storeLastFocusedElement_: function() {
+ if (this.pageDiv.contains(document.activeElement))
+ this.lastFocusedElement = document.activeElement;
+ },
+
+ /**
+ * Restores focus to the last focused element on this page.
+ * @private
+ */
+ restoreLastFocusedElement_: function() {
+ if (this.lastFocusedElement)
+ this.lastFocusedElement.focus();
+ else
+ this.focus();
+ },
+
+ /**
+ * Shows or hides current page iff it's an overlay.
+ * @param {boolean} visible True if overlay should be displayed.
+ * @private
+ */
+ setOverlayVisible_: function(visible) {
+ assert(this.isOverlay);
+ var pageDiv = this.pageDiv;
+ this.container.hidden = !visible;
+ if (visible)
+ pageDiv.classList.add('showing');
+ else
+ pageDiv.classList.remove('showing');
+ },
+
+ /**
+ * @return {HTMLDivElement} visible non-overlay page or
+ * null, if there are no visible non-overlay pages.
+ * @private
+ */
+ getVisibleNonOverlay_: function() {
+ if (this.isOverlay || !this.visible)
+ return null;
+ return this;
+ },
+
+ /**
+ * @return {HTMLDivElement} Visible overlay page, or null,
+ * if there are no visible overlay pages.
+ * @private
+ */
+ getVisibleOverlay_: function() {
+ for (var name in this.registeredOverlays) {
+ var overlay = this.registeredOverlays[name];
+ if (overlay.visible)
+ return overlay;
+ }
+ return null;
+ },
+
+ /**
+ * Freezes current page, makes it impossible to scroll it.
+ * @param {boolean} freeze True if the page should be frozen.
+ * @private
+ */
+ freeze_: function(freeze) {
+ if (freeze) {
+ this.lastScrollTop = document.documentElement.scrollTop;
+ document.body.style.overflow = 'hidden';
+ window.scroll(document.body.scrollLeft, 0);
+ } else {
+ document.body.style.overflow = 'auto';
+ window.scroll(document.body.scrollLeft, this.lastScrollTop);
+ }
+ },
+
+ /**
+ * Initializes current page.
+ * @param {string} name Name of the current page.
+ */
+ initialize: function(name) {
+ this.name = name;
+ this.pageDiv = $(name);
+ },
+
+ /**
+ * @return {HTMLDivElement} Topmost visible page, or null, if
+ * there are no visible pages.
+ */
+ getTopmostVisiblePage: function() {
+ return this.getVisibleOverlay_() || this.getVisibleNonOverlay_();
+ },
+
+ /**
+ * Registers overlay.
+ * @param {HelpBasePage} overlay Overlay that should be registered.
+ */
+ registerOverlay: function(overlay) {
+ this.registeredOverlays[overlay.name] = overlay;
+ overlay.isOverlay = true;
+ },
+
+ /**
+ * Shows or hides current page.
+ * @param {boolean} visible True if current page should be displayed.
+ */
+ set visible(visible) {
+ if (this.visible == visible)
+ return;
+
+ if (!visible)
+ this.storeLastFocusedElement_();
+
+ if (this.isOverlay)
+ this.setOverlayVisible_(visible);
+ else
+ this.pageDiv.hidden = !visible;
+
+ if (visible)
+ this.restoreLastFocusedElement_();
+ },
+
+ /**
+ * Returns true if current page is visible.
+ * @return {boolean} True if current page is visible.
+ */
+ get visible() {
+ if (this.isOverlay)
+ return this.pageDiv.classList.contains('showing');
+ return !this.pageDiv.hidden;
+ },
+
+ /**
+ * This method returns overlay container, it should be called only
+ * on overlays.
+ * @return {HTMLDivElement} overlay container.
+ */
+ get container() {
+ assert(this.isOverlay);
+ return this.pageDiv.parentNode;
+ },
+
+ /**
+ * Shows registered overlay.
+ * @param {string} name Name of registered overlay to show.
+ */
+ showOverlay: function(name) {
+ var currentPage = this.getTopmostVisiblePage();
+ currentPage.storeLastFocusedElement_();
+ currentPage.freeze_(true);
+
+ var overlay = this.registeredOverlays[name];
+ if (!overlay)
+ return;
+ overlay.visible = true;
+ },
+
+ /**
+ * Hides currently displayed overlay.
+ */
+ closeOverlay: function() {
+ var overlay = this.getVisibleOverlay_();
+ if (!overlay)
+ return;
+ overlay.visible = false;
+
+ var currentPage = this.getTopmostVisiblePage();
+ currentPage.restoreLastFocusedElement_();
+ currentPage.freeze_(false);
+ },
+
+ /**
+ * If the page does not contain focused elements, focuses on the
+ * first appropriate.
+ */
+ focus: function() {
+ if (this.pageDiv.contains(document.activeElement))
+ return;
+ var elements = this.pageDiv.querySelectorAll(
+ 'input, list, select, textarea, button');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ element.focus();
+ if (document.activeElement == element)
+ return;
+ }
+ },
+ };
+
+ // Export
+ return {
+ HelpBasePage: HelpBasePage
+ };
+});
diff --git a/chrome/browser/resources/help/help_focus_manager.js b/chrome/browser/resources/help/help_focus_manager.js
new file mode 100644
index 0000000..335f8fd
--- /dev/null
+++ b/chrome/browser/resources/help/help_focus_manager.js
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+// Helper class for help page, that controls focus transition between
+// elements on the help page and overlays.
+cr.define('help', function() {
+ function HelpFocusManager() {
+ }
+
+ cr.addSingletonGetter(HelpFocusManager);
+
+ HelpFocusManager.prototype = {
+ __proto__: cr.ui.FocusManager.prototype,
+
+ getFocusParent: function() {
+ var page = help.HelpPage.getTopmostVisiblePage();
+ if (!page)
+ return null;
+ return page.pageDiv;
+ },
+ };
+
+ return {
+ HelpFocusManager: HelpFocusManager,
+ };
+});