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

Unified Diff: third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js

Issue 1862213002: Roll third_party/polymer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove obsolete appearance_browsertest.js, result of a previous bad merge. Created 4 years, 8 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: third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js
index b8a165b1d4ab3455c7bdf856995c93d09f407b6e..0b4df854eca328c15dd1681d32136b450989efa0 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js
@@ -1,195 +1,356 @@
/**
* @struct
* @constructor
+ * @private
*/
Polymer.IronOverlayManagerClass = function() {
+ /**
+ * Used to keep track of the opened overlays.
+ * @private {Array<Element>}
+ */
this._overlays = [];
- // Used to keep track of the last focused node before an overlay gets opened.
- this._lastFocusedNodes = [];
/**
- * iframes have a default z-index of 100, so this default should be at least
- * that.
+ * iframes have a default z-index of 100,
+ * so this default should be at least that.
* @private {number}
*/
this._minimumZ = 101;
- this._backdrops = [];
-
+ /**
+ * Memoized backdrop element.
+ * @private {Element|null}
+ */
this._backdropElement = null;
- Object.defineProperty(this, 'backdropElement', {
- get: function() {
- if (!this._backdropElement) {
- this._backdropElement = document.createElement('iron-overlay-backdrop');
- }
- return this._backdropElement;
- }.bind(this)
- });
+
+ // Listen to mousedown or touchstart to be sure to be the first to capture
+ // clicks outside the overlay.
+ var clickEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown';
+ document.addEventListener(clickEvent, this._onCaptureClick.bind(this), true);
+ document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
+ document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
+ };
+
+ Polymer.IronOverlayManagerClass.prototype = {
+
+ constructor: Polymer.IronOverlayManagerClass,
+
+ /**
+ * The shared backdrop element.
+ * @type {Element} backdropElement
+ */
+ get backdropElement() {
+ if (!this._backdropElement) {
+ this._backdropElement = document.createElement('iron-overlay-backdrop');
+ }
+ return this._backdropElement;
+ },
/**
* The deepest active element.
- * returns {?Node} element the active element
- */
- this.deepActiveElement = null;
- Object.defineProperty(this, 'deepActiveElement', {
- get: function() {
- var active = document.activeElement;
- // document.activeElement can be null
- // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
- while (active && active.root && Polymer.dom(active.root).activeElement) {
- active = Polymer.dom(active.root).activeElement;
- }
- return active;
- }.bind(this)
- });
- };
+ * @type {Element} activeElement the active element
+ */
+ get deepActiveElement() {
+ // document.activeElement can be null
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
+ // In case of null, default it to document.body.
+ var active = document.activeElement || document.body;
+ while (active.root && Polymer.dom(active.root).activeElement) {
+ active = Polymer.dom(active.root).activeElement;
+ }
+ return active;
+ },
- /**
- * If a node is contained in an overlay.
- * @private
- * @param {Node} node
- * @returns {Boolean}
- */
- Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) {
- while (node && node !== document.body) {
- // Use logical parentNode, or native ShadowRoot host.
- node = Polymer.dom(node).parentNode || node.host;
- // Check if it is an overlay.
- if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
- return true;
+ /**
+ * Brings the overlay at the specified index to the front.
+ * @param {number} i
+ * @private
+ */
+ _bringOverlayAtIndexToFront: function(i) {
+ var overlay = this._overlays[i];
+ var lastI = this._overlays.length - 1;
+ // Ensure always-on-top overlay stays on top.
+ if (!overlay.alwaysOnTop && this._overlays[lastI].alwaysOnTop) {
+ lastI--;
+ }
+ // If already the top element, return.
+ if (!overlay || i >= lastI) {
+ return;
+ }
+ // Update z-index to be on top.
+ var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
+ if (this._getZ(overlay) <= minimumZ) {
+ this._applyOverlayZ(overlay, minimumZ);
}
- }
- return false;
- };
- Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, aboveZ) {
- this._setZ(overlay, aboveZ + 2);
- };
+ // Shift other overlays behind the new on top.
+ while (i < lastI) {
+ this._overlays[i] = this._overlays[i + 1];
+ i++;
+ }
+ this._overlays[lastI] = overlay;
+ },
- Polymer.IronOverlayManagerClass.prototype._setZ = function(element, z) {
- element.style.zIndex = z;
- };
+ /**
+ * Adds the overlay and updates its z-index if it's opened, or removes it if it's closed.
+ * Also updates the backdrop z-index.
+ * @param {Element} overlay
+ */
+ addOrRemoveOverlay: function(overlay) {
+ if (overlay.opened) {
+ this.addOverlay(overlay);
+ } else {
+ this.removeOverlay(overlay);
+ }
+ this.trackBackdrop();
+ },
- /**
- * track overlays for z-index and focus managemant
- */
- Polymer.IronOverlayManagerClass.prototype.addOverlay = function(overlay) {
- var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
- this._overlays.push(overlay);
- var newZ = this.currentOverlayZ();
- if (newZ <= minimumZ) {
- this._applyOverlayZ(overlay, minimumZ);
- }
- var element = this.deepActiveElement;
- // If already in other overlay, don't reset focus there.
- if (this._isChildOfOverlay(element)) {
- element = null;
- }
- this._lastFocusedNodes.push(element);
- };
+ /**
+ * Tracks overlays for z-index and focus management.
+ * Ensures the last added overlay with always-on-top remains on top.
+ * @param {Element} overlay
+ */
+ addOverlay: function(overlay) {
+ var i = this._overlays.indexOf(overlay);
+ if (i >= 0) {
+ this._bringOverlayAtIndexToFront(i);
+ return;
+ }
+ var insertionIndex = this._overlays.length;
+ var currentOverlay = this._overlays[insertionIndex - 1];
+ var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
+ var newZ = this._getZ(overlay);
+
+ // Ensure always-on-top overlay stays on top.
+ if (currentOverlay && currentOverlay.alwaysOnTop && !overlay.alwaysOnTop) {
+ // This bumps the z-index of +2.
+ this._applyOverlayZ(currentOverlay, minimumZ);
+ insertionIndex--;
+ // Update minimumZ to match previous overlay's z-index.
+ var previousOverlay = this._overlays[insertionIndex - 1];
+ minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
+ }
+
+ // Update z-index and insert overlay.
+ if (newZ <= minimumZ) {
+ this._applyOverlayZ(overlay, minimumZ);
+ }
+ this._overlays.splice(insertionIndex, 0, overlay);
- Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) {
- var i = this._overlays.indexOf(overlay);
- if (i >= 0) {
+ // Get focused node.
+ var element = this.deepActiveElement;
+ overlay.restoreFocusNode = this._overlayParent(element) ? null : element;
+ },
+
+ /**
+ * @param {Element} overlay
+ */
+ removeOverlay: function(overlay) {
+ var i = this._overlays.indexOf(overlay);
+ if (i === -1) {
+ return;
+ }
this._overlays.splice(i, 1);
- this._setZ(overlay, '');
- var node = this._lastFocusedNodes[i];
- // Focus only if still contained in document.body
- if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
+ var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null;
+ overlay.restoreFocusNode = null;
+ // Focus back only if still contained in document.body
+ if (node && Polymer.dom(document.body).deepContains(node)) {
node.focus();
}
- this._lastFocusedNodes.splice(i, 1);
- }
- };
+ },
- Polymer.IronOverlayManagerClass.prototype.currentOverlay = function() {
- var i = this._overlays.length - 1;
- while (this._overlays[i] && !this._overlays[i].opened) {
- --i;
- }
- return this._overlays[i];
- };
+ /**
+ * Returns the current overlay.
+ * @return {Element|undefined}
+ */
+ currentOverlay: function() {
+ var i = this._overlays.length - 1;
+ return this._overlays[i];
+ },
- Polymer.IronOverlayManagerClass.prototype.currentOverlayZ = function() {
- return this._getOverlayZ(this.currentOverlay());
- };
+ /**
+ * Returns the current overlay z-index.
+ * @return {number}
+ */
+ currentOverlayZ: function() {
+ return this._getZ(this.currentOverlay());
+ },
- /**
- * Ensures that the minimum z-index of new overlays is at least `minimumZ`.
- * This does not effect the z-index of any existing overlays.
- *
- * @param {number} minimumZ
- */
- Polymer.IronOverlayManagerClass.prototype.ensureMinimumZ = function(minimumZ) {
- this._minimumZ = Math.max(this._minimumZ, minimumZ);
- };
+ /**
+ * Ensures that the minimum z-index of new overlays is at least `minimumZ`.
+ * This does not effect the z-index of any existing overlays.
+ * @param {number} minimumZ
+ */
+ ensureMinimumZ: function(minimumZ) {
+ this._minimumZ = Math.max(this._minimumZ, minimumZ);
+ },
- Polymer.IronOverlayManagerClass.prototype.focusOverlay = function() {
- var current = this.currentOverlay();
- // We have to be careful to focus the next overlay _after_ any current
- // transitions are complete (due to the state being toggled prior to the
- // transition). Otherwise, we risk infinite recursion when a transitioning
- // (closed) overlay becomes the current overlay.
- //
- // NOTE: We make the assumption that any overlay that completes a transition
- // will call into focusOverlay to kick the process back off. Currently:
- // transitionend -> _applyFocus -> focusOverlay.
- if (current && !current.transitioning) {
- current._applyFocus();
- }
- };
+ focusOverlay: function() {
+ var current = /** @type {?} */ (this.currentOverlay());
+ // We have to be careful to focus the next overlay _after_ any current
+ // transitions are complete (due to the state being toggled prior to the
+ // transition). Otherwise, we risk infinite recursion when a transitioning
+ // (closed) overlay becomes the current overlay.
+ //
+ // NOTE: We make the assumption that any overlay that completes a transition
+ // will call into focusOverlay to kick the process back off. Currently:
+ // transitionend -> _applyFocus -> focusOverlay.
+ if (current && !current.transitioning) {
+ current._applyFocus();
+ }
+ },
- Polymer.IronOverlayManagerClass.prototype.trackBackdrop = function(element) {
- // backdrops contains the overlays with a backdrop that are currently
- // visible
- var index = this._backdrops.indexOf(element);
- if (element.opened && element.withBackdrop) {
- // no duplicates
- if (index === -1) {
- this._backdrops.push(element);
- }
- } else if (index >= 0) {
- this._backdrops.splice(index, 1);
- }
- };
+ /**
+ * Updates the backdrop z-index.
+ */
+ trackBackdrop: function() {
+ this.backdropElement.style.zIndex = this.backdropZ();
+ },
- Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() {
- return this._backdrops;
- };
+ /**
+ * @return {Array<Element>}
+ */
+ getBackdrops: function() {
+ var backdrops = [];
+ for (var i = 0; i < this._overlays.length; i++) {
+ if (this._overlays[i].withBackdrop) {
+ backdrops.push(this._overlays[i]);
+ }
+ }
+ return backdrops;
+ },
- /**
- * Returns the z-index for the backdrop.
- */
- Polymer.IronOverlayManagerClass.prototype.backdropZ = function() {
- return this._getOverlayZ(this._overlayWithBackdrop()) - 1;
- };
+ /**
+ * Returns the z-index for the backdrop.
+ * @return {number}
+ */
+ backdropZ: function() {
+ return this._getZ(this._overlayWithBackdrop()) - 1;
+ },
- /**
- * Returns the first opened overlay that has a backdrop.
- */
- Polymer.IronOverlayManagerClass.prototype._overlayWithBackdrop = function() {
- for (var i = 0; i < this._overlays.length; i++) {
- if (this._overlays[i].opened && this._overlays[i].withBackdrop) {
- return this._overlays[i];
+ /**
+ * Returns the first opened overlay that has a backdrop.
+ * @return {Element|undefined}
+ * @private
+ */
+ _overlayWithBackdrop: function() {
+ for (var i = 0; i < this._overlays.length; i++) {
+ if (this._overlays[i].withBackdrop) {
+ return this._overlays[i];
+ }
}
- }
- };
+ },
- /**
- * Calculates the minimum z-index for the overlay.
- */
- Polymer.IronOverlayManagerClass.prototype._getOverlayZ = function(overlay) {
- var z = this._minimumZ;
- if (overlay) {
- var z1 = Number(window.getComputedStyle(overlay).zIndex);
- // Check if is a number
- // Number.isNaN not supported in IE 10+
- if (z1 === z1) {
- z = z1;
+ /**
+ * Calculates the minimum z-index for the overlay.
+ * @param {Element=} overlay
+ * @private
+ */
+ _getZ: function(overlay) {
+ var z = this._minimumZ;
+ if (overlay) {
+ var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).zIndex);
+ // Check if is a number
+ // Number.isNaN not supported in IE 10+
+ if (z1 === z1) {
+ z = z1;
+ }
+ }
+ return z;
+ },
+
+ /**
+ * @param {Element} element
+ * @param {number|string} z
+ * @private
+ */
+ _setZ: function(element, z) {
+ element.style.zIndex = z;
+ },
+
+ /**
+ * @param {Element} overlay
+ * @param {number} aboveZ
+ * @private
+ */
+ _applyOverlayZ: function(overlay, aboveZ) {
+ this._setZ(overlay, aboveZ + 2);
+ },
+
+ /**
+ * Returns the overlay containing the provided node. If the node is an overlay,
+ * it returns the node.
+ * @param {Element=} node
+ * @return {Element|undefined}
+ * @private
+ */
+ _overlayParent: function(node) {
+ while (node && node !== document.body) {
+ // Check if it is an overlay.
+ if (node._manager === this) {
+ return node;
+ }
+ // Use logical parentNode, or native ShadowRoot host.
+ node = Polymer.dom(node).parentNode || node.host;
+ }
+ },
+
+ /**
+ * Returns the deepest overlay in the path.
+ * @param {Array<Element>=} path
+ * @return {Element|undefined}
+ * @private
+ */
+ _overlayInPath: function(path) {
+ path = path || [];
+ for (var i = 0; i < path.length; i++) {
+ if (path[i]._manager === this) {
+ return path[i];
+ }
+ }
+ },
+
+ /**
+ * Ensures the click event is delegated to the right overlay.
+ * @param {!Event} event
+ * @private
+ */
+ _onCaptureClick: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ // Check if clicked outside of top overlay.
+ if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
+ overlay._onCaptureClick(event);
+ }
+ },
+
+ /**
+ * Ensures the focus event is delegated to the right overlay.
+ * @param {!Event} event
+ * @private
+ */
+ _onCaptureFocus: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ if (overlay) {
+ overlay._onCaptureFocus(event);
+ }
+ },
+
+ /**
+ * Ensures TAB and ESC keyboard events are delegated to the right overlay.
+ * @param {!Event} event
+ * @private
+ */
+ _onCaptureKeyDown: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ if (overlay) {
+ if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
+ overlay._onCaptureEsc(event);
+ } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'tab')) {
+ overlay._onCaptureTab(event);
+ }
}
}
- return z;
};
Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();

Powered by Google App Engine
This is Rietveld 408576698