Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2996)

Unified Diff: chrome/browser/resources/md_bookmarks/dialog_focus_manager.js

Issue 2954273002: [MD Bookmarks] Restore focus after closing a dialog or context menu. (Closed)
Patch Set: fix deps Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
diff --git a/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js b/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b3879d72a2cd6bd36981149bd1be1dca4831066
--- /dev/null
+++ b/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
@@ -0,0 +1,102 @@
+// Copyright 2017 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.
+
+cr.define('bookmarks', function() {
+ /**
+ * Manages focus restoration for modal dialogs. After the final dialog in a
+ * stack is closed, restores focus to the element which was focused when the
+ * first dialog was opened.
+ * @constructor
+ */
+ function DialogFocusManager() {
+ /** @private {HTMLElement} */
+ this.previousFocusElement_ = null;
+
+ /** @private {boolean} */
+ this.previousMouseFocus_ = false;
+
+ /** @private {Set<HTMLDialogElement>} */
+ this.dialogs_ = new Set();
+ }
+
+ DialogFocusManager.prototype = {
+ /**
+ * @param {HTMLDialogElement} dialog
+ * @param {function()=} showFn
+ */
+ showDialog: function(dialog, showFn) {
+ if (!showFn) {
+ showFn = function() {
+ dialog.showModal();
+ };
+ }
+
+ // Update the focus if there are no open dialogs or if this is the only
+ // dialog and it's getting reshown.
+ if (!this.dialogs_.size ||
+ (this.dialogs_.has(dialog) && this.dialogs_.size == 1)) {
+ this.updatePreviousFocus_();
+ }
+
+ if (!this.dialogs_.has(dialog)) {
+ dialog.addEventListener('close', this.getCloseListener_(dialog));
+ this.dialogs_.add(dialog);
+ }
+
+ showFn();
+ },
+
+ /** @private */
+ updatePreviousFocus_: function() {
+ this.previousFocusElement_ = this.getFocusedElement_();
+ this.previousMouseFocus_ = bookmarks.MouseFocusBehavior.isMouseFocused(
+ this.previousFocusElement_);
+ },
+
+ /**
+ * @return {HTMLElement}
+ * @private
+ */
+ getFocusedElement_: function() {
+ var focus = document.activeElement;
+ while (focus.root && focus.root.activeElement)
+ focus = focus.root.activeElement;
+
+ return focus;
+ },
+
+ /**
+ * @param {HTMLDialogElement} dialog
+ * @return {function(Event)}
+ * @private
+ */
+ getCloseListener_: function(dialog) {
+ var closeListener = function(e) {
+ // If the dialog is open, then it got reshown immediately and we
+ // shouldn't clear it until it is closed again.
+ if (dialog.open)
+ return;
+
+ assert(this.dialogs_.delete(dialog));
+ // Focus the originally focused element if there are no more dialogs.
+ if (!this.dialogs_.size) {
+ this.previousFocusElement_.focus();
+ if (this.previousMouseFocus_) {
+ bookmarks.MouseFocusBehavior.addMouseFocusClass(
+ this.previousFocusElement_);
+ }
+ }
+ dialog.removeEventListener('close', closeListener);
+ }.bind(this);
+
+ return closeListener;
+ },
+ };
+
+ cr.addSingletonGetter(DialogFocusManager);
+
+ return {
+ DialogFocusManager: DialogFocusManager,
+ };
+});

Powered by Google App Engine
This is Rietveld 408576698