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

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

Issue 2402553002: MD Settings: Implementing modal popup/action menus. (Closed)
Patch Set: Fix RTL 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: 'settings-action-menu',
7 extends: 'dialog',
8
9 /**
10 * List of all options in this action menu.
11 * @private {?NodeList<!Element>}
12 */
13 options_: 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,
27
28 /** override */
29 attached: function() {
30 this.setAttribute('tabindex', 0);
31 this.options_ = this.querySelectorAll('.dropdown-item');
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') {
63 return;
64 }
65
66 var nextOption = this.getNextOption_(
67 e.key == 'ArrowDown' || e.key == 'ArrowRight' ? 1 : - 1);
68 if (nextOption !== null)
69 nextOption.focus();
70
71 e.preventDefault();
72 }.bind(this));
73 },
74
75 /**
76 * @param {number} step -1 for getting previous option (up), 1 for getting
77 * next option (down).
78 * @return {?HTMLElement} The next focusable option, taking into account
79 * disabled/hidden attributes, or null if no focusable option exists.
80 * @private
81 */
82 getNextOption_: function(step) {
83 // Storing the focused index before searching, to avoid infinite loop if all
84 // options are disabled.
85 var previousFocusedIndex = this.focusedIndex_;
86
87 var getNextOptionRec_ = function() {
88 // Advance index.
89 this.focusedIndex_ = (this.focusedIndex_ + step) % this.options_.length;
90 if (this.focusedIndex_ == -1)
91 this.focusedIndex_ = this.options_.length - 1;
92
93 // Adjust index in case item is disabled/hidden.
94 var nextOption = this.options_[this.focusedIndex_];
95 if (nextOption.disabled || nextOption.hidden) {
96 return this.focusedIndex_ != previousFocusedIndex ?
97 getNextOptionRec_() : null;
98 } else {
99 return this.options_[this.focusedIndex_];
100 }
101 }.bind(this);
102
103 return getNextOptionRec_();
104 },
105
106 /**
107 * Shows the menu anchored to the given rectangle.
108 * @param {!ClientRect} rect
109 */
110 showAtLocation: function(rect) {
111 // Ensure that the correct item is focused when the dialog is shown, by
112 // setting the 'autofocus' attribute.
113 this.focusedIndex_ = 0;
114 var nextOption = this.options_[this.focusedIndex_];
115 if (nextOption.disabled || nextOption.hidden)
116 nextOption = this.getNextOption_(1);
117 for (var option of this.options_)
118 option.removeAttribute('autofocus');
119 if (nextOption !== null)
120 nextOption.setAttribute('autofocus', true);
121
122 this.showModal();
123
124 var directionDelegate = new settings.DirectionDelegateImpl();
125 if (directionDelegate.isRtl()) {
126 var right = window.innerWidth - rect.left - this.offsetWidth;
127 this.style.right = right + 'px';
dpapad 2016/10/13 00:23:17 I don't know if this is a blink bug, but - when R
Dan Beam 2016/10/13 00:28:34 no, that's known
128 } else {
129 var left = rect.right - this.offsetWidth;
130 this.style.left = left + 'px';
131 }
132
133 // Attempt to show the menu starting from the top of the rectangle and
134 // extending downwards. If that does not fit within the window, fallback to
135 // starting from the bottom and extending upwards.
136 var top = rect.top + this.offsetHeight <= window.innerHeight ?
137 rect.top :
138 rect.bottom - this.offsetHeight - Math.max(
139 rect.bottom - window.innerHeight, 0);
140
141 this.style.top = top + 'px';
142 },
143 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/settings/settings_action_menu.html ('k') | chrome/browser/resources/settings/settings_resources.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698