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

Side by Side Diff: chrome/browser/resources/settings/cr_action_menu.js

Issue 2402553002: MD Settings: Implementing modal popup/action menus. (Closed)
Patch Set: Position smarter. Created 4 years, 2 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 Polymer({
6 is: 'cr-action-menu',
7 extends: 'dialog',
8
9 /**
10 * List of all options in this action menu.
11 * @private {?HTMLElement}
12 */
13 buttons_: null,
14
15 /**
16 * Index of the currently focused item.
17 * @private {number}
18 */
19 focusedIndex_: 0,
20
21 /**
22 * Reference to the bound window's resize listener, such that it can be
23 * removed on detach.
24 * @private {?Function}
25 */
26 onWindowResize_: null,
Dan Beam 2016/10/13 00:28:34 nit: just do this after the ctor as like "boundRes
dpapad 2016/10/13 00:51:22 By ctor do you mean "attached"?
27
28 /** override */
29 attached: function() {
30 this.setAttribute('tabindex', 0);
31 this.buttons_ = this.querySelectorAll('button');
32
33 this.onWindowResize_ = function() {
34 if (this.open)
35 this.close();
36 }.bind(this);
37
38 window.addEventListener('resize', this.onWindowResize_);
39 },
40
41 /** override */
42 detached: function() {
43 window.removeEventListener('resize', this.onWindowResize_);
44 },
45
46 /** @override */
47 ready: function() {
48 this.addEventListener('click', function(e) {
49 if (e.target == this) {
50 this.close();
51 e.stopPropagation();
52 }
53 }.bind(this));
54
55 this.addEventListener('keydown', function(e) {
56 if (e.key == 'Tab') {
57 this.close();
58 return;
59 }
60
61 if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' &&
62 e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') {
Dan Beam 2016/10/13 00:28:34 nit: just drop 'ArrowLeft' and 'ArrowRight' for no
dpapad 2016/10/13 00:51:22 Done.
63 return;
64 }
65
66 var nextButton = this.getNextButton_(
67 e.key == 'ArrowDown' || e.key == 'ArrowRight' ? 1 : - 1);
68 if (nextButton !== null)
Dan Beam 2016/10/13 00:28:33 if (nextButton)
dpapad 2016/10/13 00:51:22 Done.
69 nextButton.focus();
70
71 e.preventDefault();
72 }.bind(this));
73 },
74
75 /**
76 * @param {number} step -1 for getting previous button (up), 1 for getting
77 * next button (down).
78 * @return {?HTMLElement} The next option to be focused, taking into account
79 * disabled options, or null if all options are disabled.
80 * @private
81 */
82 getNextButton_: function(step) {
83 // Storing the focused index before searching, to avoid infinite loop if all
84 // buttons are disabled.
85 var previousFocusedIndex = this.focusedIndex_;
86
87 var getNextButtonRec_ = function() {
88 // Advanced index.
89 this.focusedIndex_ = (this.focusedIndex_ + step) % this.buttons_.length;
90 if (this.focusedIndex_ == -1)
91 this.focusedIndex_ = this.buttons_.length - 1;
92
93 // Adjust index in case item is disabled.
94 if (this.buttons_[this.focusedIndex_].disabled) {
95 return this.focusedIndex_ != previousFocusedIndex ?
96 getNextButtonRec_() : null;
97 } else {
98 return this.buttons_[this.focusedIndex_];
99 }
100 }.bind(this);
101
102 return getNextButtonRec_();
103 },
104
105 /**
106 * Shows the menu anchored to the given rectangle.
107 * @param {!ClientRect} rect
108 */
109 showAtLocation: function(rect) {
110 this.showModal();
Dan Beam 2016/10/13 00:28:34 why does showModal() happen before positioning?
dpapad 2016/10/13 00:51:22 Because this.offsetWidth, this.offsetHeight are no
111 this.focusedIndex_ = 0;
112
113 var left = rect.right - this.offsetWidth;
114
115 // Attempt to show the menu starting from the top of the rectangle and
116 // extending downwards. If that does not fit within the window, fallback to
117 // starting from the bottom and extending upwards.
118 var top = rect.top + this.offsetHeight <= window.innerHeight ?
119 rect.top :
120 rect.bottom - this.offsetHeight - Math.max(
121 rect.bottom - window.innerHeight, 0);
122
123 this.style.top = top + 'px';
124 this.style.left = left + 'px';
125 },
126 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698