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

Side by Side Diff: ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js

Issue 2708863004: WebUI: Close cr-action-menu on popstate event. (Closed)
Patch Set: Add test Created 3 years, 10 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
« no previous file with comments | « chrome/test/data/webui/cr_elements/cr_action_menu_test.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 Polymer({ 5 Polymer({
6 is: 'cr-action-menu', 6 is: 'cr-action-menu',
7 extends: 'dialog', 7 extends: 'dialog',
8 8
9 /** 9 /**
10 * List of all options in this action menu. 10 * List of all options in this action menu.
11 * @private {?NodeList<!Element>} 11 * @private {?NodeList<!Element>}
12 */ 12 */
13 options_: null, 13 options_: null,
14 14
15 /** 15 /**
16 * The element which the action menu will be anchored to. Also the element 16 * The element which the action menu will be anchored to. Also the element
17 * where focus will be returned after the menu is closed. 17 * where focus will be returned after the menu is closed.
18 * @private {?Element} 18 * @private {?Element}
19 */ 19 */
20 anchorElement_: null, 20 anchorElement_: null,
21 21
22 /** 22 /**
23 * Reference to the bound window's resize listener, such that it can be 23 * Bound reference to an event listener function such that it can be removed
24 * removed on detach. 24 * on detach.
25 * @private {?Function} 25 * @private {?Function}
26 */ 26 */
27 onWindowResize_: null, 27 boundClose_: null,
28 28
29 hostAttributes: { 29 hostAttributes: {
30 tabindex: 0, 30 tabindex: 0,
31 }, 31 },
32 32
33 listeners: { 33 listeners: {
34 'keydown': 'onKeyDown_', 34 'keydown': 'onKeyDown_',
35 'tap': 'onTap_', 35 'tap': 'onTap_',
36 }, 36 },
37 37
38 /** override */ 38 /** override */
39 attached: function() { 39 attached: function() {
40 this.options_ = this.querySelectorAll('.dropdown-item'); 40 this.options_ = this.querySelectorAll('.dropdown-item');
41 }, 41 },
42 42
43 /** override */ 43 /** override */
44 detached: function() { 44 detached: function() {
45 this.removeResizeListener_(); 45 this.removeListeners_();
46 }, 46 },
47 47
48 /** @private */ 48 /** @private */
49 removeResizeListener_: function() { 49 removeListeners_: function() {
50 window.removeEventListener('resize', this.onWindowResize_); 50 window.removeEventListener('resize', this.boundClose_);
51 window.removeEventListener('popstate', this.boundClose_);
51 }, 52 },
52 53
53 /** 54 /**
54 * @param {!Event} e 55 * @param {!Event} e
55 * @private 56 * @private
56 */ 57 */
57 onTap_: function(e) { 58 onTap_: function(e) {
58 if (e.target == this) { 59 if (e.target == this) {
59 this.close(); 60 this.close();
60 e.stopPropagation(); 61 e.stopPropagation();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 if (nextOption.disabled || nextOption.hidden) 105 if (nextOption.disabled || nextOption.hidden)
105 nextOption = null; 106 nextOption = null;
106 counter++; 107 counter++;
107 } while (!nextOption && counter < numOptions); 108 } while (!nextOption && counter < numOptions);
108 109
109 return nextOption; 110 return nextOption;
110 }, 111 },
111 112
112 /** @override */ 113 /** @override */
113 close: function() { 114 close: function() {
114 // Removing 'resize' listener when dialog is closed. 115 // Removing 'resize' and 'popstate' listeners when dialog is closed.
115 this.removeResizeListener_(); 116 this.removeListeners_();
116 HTMLDialogElement.prototype.close.call(this); 117 HTMLDialogElement.prototype.close.call(this);
117 this.anchorElement_.focus(); 118 this.anchorElement_.focus();
118 this.anchorElement_ = null; 119 this.anchorElement_ = null;
119 }, 120 },
120 121
121 /** 122 /**
122 * Shows the menu anchored to the given element. 123 * Shows the menu anchored to the given element.
123 * @param {!Element} anchorElement 124 * @param {!Element} anchorElement
124 */ 125 */
125 showAt: function(anchorElement) { 126 showAt: function(anchorElement) {
126 this.anchorElement_ = anchorElement; 127 this.anchorElement_ = anchorElement;
127 this.onWindowResize_ = this.onWindowResize_ || function() { 128 this.boundClose_ = this.boundClose_ || function() {
128 if (this.open) 129 if (this.open)
129 this.close(); 130 this.close();
130 }.bind(this); 131 }.bind(this);
131 window.addEventListener('resize', this.onWindowResize_); 132 window.addEventListener('resize', this.boundClose_);
133 window.addEventListener('popstate', this.boundClose_);
132 134
133 // Reset position to prevent previous values from affecting layout. 135 // Reset position to prevent previous values from affecting layout.
134 this.style.left = ''; 136 this.style.left = '';
135 this.style.right = ''; 137 this.style.right = '';
136 this.style.top = ''; 138 this.style.top = '';
137 139
138 this.showModal(); 140 this.showModal();
139 141
140 var rect = this.anchorElement_.getBoundingClientRect(); 142 var rect = this.anchorElement_.getBoundingClientRect();
141 if (getComputedStyle(this.anchorElement_).direction == 'rtl') { 143 if (getComputedStyle(this.anchorElement_).direction == 'rtl') {
142 var right = window.innerWidth - rect.left - this.offsetWidth; 144 var right = window.innerWidth - rect.left - this.offsetWidth;
143 this.style.right = right + 'px'; 145 this.style.right = right + 'px';
144 } else { 146 } else {
145 var left = rect.right - this.offsetWidth; 147 var left = rect.right - this.offsetWidth;
146 this.style.left = left + 'px'; 148 this.style.left = left + 'px';
147 } 149 }
148 150
149 // Attempt to show the menu starting from the top of the rectangle and 151 // Attempt to show the menu starting from the top of the rectangle and
150 // extending downwards. If that does not fit within the window, fallback to 152 // extending downwards. If that does not fit within the window, fallback to
151 // starting from the bottom and extending upwards. 153 // starting from the bottom and extending upwards.
152 var top = rect.top + this.offsetHeight <= window.innerHeight ? rect.top : 154 var top = rect.top + this.offsetHeight <= window.innerHeight ? rect.top :
153 rect.bottom - 155 rect.bottom -
154 this.offsetHeight - Math.max(rect.bottom - window.innerHeight, 0); 156 this.offsetHeight - Math.max(rect.bottom - window.innerHeight, 0);
155 157
156 this.style.top = top + 'px'; 158 this.style.top = top + 'px';
157 }, 159 },
158 }); 160 });
OLDNEW
« no previous file with comments | « chrome/test/data/webui/cr_elements/cr_action_menu_test.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698