| Index: ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
|
| diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
|
| index 17b91df4af7ed32d2e72a4c742a5c0c1f8b25912..5979235e5c761c4d75adf71b9217044756a4cd6c 100644
|
| --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
|
| +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
|
| @@ -6,14 +6,14 @@
|
| * @typedef {{
|
| * top: number,
|
| * left: number,
|
| - * width: (number| undefined),
|
| - * height: (number| undefined),
|
| - * anchorAlignmentX: (number| undefined),
|
| - * anchorAlignmentY: (number| undefined),
|
| - * minX: (number| undefined),
|
| - * minY: (number| undefined),
|
| - * maxX: (number| undefined),
|
| - * maxY: (number| undefined),
|
| + * width: (number|undefined),
|
| + * height: (number|undefined),
|
| + * anchorAlignmentX: (number|undefined),
|
| + * anchorAlignmentY: (number|undefined),
|
| + * minX: (number|undefined),
|
| + * minY: (number|undefined),
|
| + * maxX: (number|undefined),
|
| + * maxY: (number|undefined),
|
| * }}
|
| */
|
| var ShowConfig;
|
| @@ -73,12 +73,12 @@ function getStartPointWithAnchor(
|
| return startPoint;
|
| }
|
|
|
| -
|
| /**
|
| * @private
|
| * @return {!ShowConfig}
|
| */
|
| function getDefaultShowConfig() {
|
| + var doc = document.scrollingElement;
|
| return {
|
| top: 0,
|
| left: 0,
|
| @@ -86,10 +86,10 @@ function getDefaultShowConfig() {
|
| width: 0,
|
| anchorAlignmentX: AnchorAlignment.AFTER_START,
|
| anchorAlignmentY: AnchorAlignment.AFTER_START,
|
| - minX: 0,
|
| - minY: 0,
|
| - maxX: window.innerWidth,
|
| - maxY: window.innerHeight,
|
| + minX: doc.scrollLeft,
|
| + minY: doc.scrollTop,
|
| + maxX: doc.scrollLeft + window.innerWidth,
|
| + maxY: doc.scrollTop + window.innerHeight,
|
| };
|
| }
|
|
|
| @@ -242,19 +242,49 @@ Polymer({
|
| /**
|
| * Shows the menu anchored to the given element.
|
| * @param {!Element} anchorElement
|
| + * @param {ShowConfig=} opt_config
|
| */
|
| - showAt: function(anchorElement) {
|
| + showAt: function(anchorElement, opt_config) {
|
| this.anchorElement_ = anchorElement;
|
| + // Scroll the anchor element into view so that the bounding rect will be
|
| + // accurate for where the menu should be shown.
|
| this.anchorElement_.scrollIntoViewIfNeeded();
|
| +
|
| + // Save the scroll position that ensures the anchor element is onscreen.
|
| + var doc = document.scrollingElement;
|
| + var scrollLeft = doc.scrollLeft;
|
| + var scrollTop = doc.scrollTop;
|
| +
|
| + // Reset position so that layout isn't affected by the previous position,
|
| + // and so that the dialog is positioned at the top-start corner of the
|
| + // document.
|
| + this.resetStyle_();
|
| +
|
| + // Show the dialog which will focus the top-start of the body. This makes
|
| + // the client rect calculation relative to the top-start of the body.
|
| + this.showModal();
|
| +
|
| var rect = this.anchorElement_.getBoundingClientRect();
|
| - this.showAtPosition({
|
| - top: rect.top,
|
| - left: rect.left,
|
| - height: rect.height,
|
| - width: rect.width,
|
| - // Default to anchoring towards the left.
|
| - anchorAlignmentX: AnchorAlignment.BEFORE_END,
|
| - });
|
| + this.positionDialog_(/** @type {ShowConfig} */ (Object.assign(
|
| + {
|
| + top: rect.top,
|
| + left: rect.left,
|
| + height: rect.height,
|
| + width: rect.width,
|
| + // Default to anchoring towards the left.
|
| + anchorAlignmentX: AnchorAlignment.BEFORE_END,
|
| + minX: scrollLeft,
|
| + minY: scrollTop,
|
| + maxX: scrollLeft + window.innerWidth,
|
| + maxY: scrollTop + window.innerHeight,
|
| + },
|
| + opt_config)));
|
| +
|
| + // Restore the scroll position.
|
| + doc.scrollTop = scrollTop;
|
| + doc.scrollLeft = scrollLeft;
|
| +
|
| + this.addCloseListeners_();
|
| },
|
|
|
| /**
|
| @@ -284,6 +314,24 @@ Polymer({
|
| * @param {!ShowConfig} config
|
| */
|
| showAtPosition: function(config) {
|
| + this.resetStyle_();
|
| + this.showModal();
|
| + this.positionDialog_(config);
|
| + this.addCloseListeners_();
|
| + },
|
| +
|
| + /** @private */
|
| + resetStyle_: function() {
|
| + this.style.left = '';
|
| + this.style.right = '';
|
| + this.style.top = '0';
|
| + },
|
| +
|
| + /**
|
| + * @param {!ShowConfig} config
|
| + * @private
|
| + */
|
| + positionDialog_: function(config) {
|
| var c = Object.assign(getDefaultShowConfig(), config);
|
|
|
| var top = c.top;
|
| @@ -291,20 +339,6 @@ Polymer({
|
| var bottom = top + c.height;
|
| var right = left + c.width;
|
|
|
| - this.boundClose_ = this.boundClose_ || function() {
|
| - if (this.open)
|
| - this.close();
|
| - }.bind(this);
|
| - window.addEventListener('resize', this.boundClose_);
|
| - window.addEventListener('popstate', this.boundClose_);
|
| -
|
| - // Reset position to prevent previous values from affecting layout.
|
| - this.style.left = '';
|
| - this.style.right = '';
|
| - this.style.top = '';
|
| -
|
| - this.showModal();
|
| -
|
| // Flip the X anchor in RTL.
|
| var rtl = getComputedStyle(this).direction == 'rtl';
|
| if (rtl)
|
| @@ -314,7 +348,7 @@ Polymer({
|
| left, right, this.offsetWidth, c.anchorAlignmentX, c.minX, c.maxX);
|
|
|
| if (rtl) {
|
| - var menuRight = window.innerWidth - menuLeft - this.offsetWidth;
|
| + var menuRight = document.body.scrollWidth - menuLeft - this.offsetWidth;
|
| this.style.right = menuRight + 'px';
|
| } else {
|
| this.style.left = menuLeft + 'px';
|
| @@ -324,5 +358,17 @@ Polymer({
|
| top, bottom, this.offsetHeight, c.anchorAlignmentY, c.minY, c.maxY);
|
| this.style.top = menuTop + 'px';
|
| },
|
| +
|
| + /**
|
| + * @private
|
| + */
|
| + addCloseListeners_: function() {
|
| + this.boundClose_ = this.boundClose_ || function() {
|
| + if (this.open)
|
| + this.close();
|
| + }.bind(this);
|
| + window.addEventListener('resize', this.boundClose_);
|
| + window.addEventListener('popstate', this.boundClose_);
|
| + },
|
| });
|
| })();
|
|
|