/FlowerClassification/venv/Lib/site-packages/external/iron_overlay_behavior/iron-overlay-manager.html
HTML | 362 lines | 316 code | 37 blank | 9 comment | 0 complexity | 39ab6a0dca8aa638e63bb7d995f5cb7f MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, 0BSD, BSD-2-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0
- <!--
- @license
- Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
- This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
- The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
- The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
- Code distributed by Google as part of the polymer project is also
- subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
- -->
- <link rel="import" href="../polymer/polymer.html">
- <link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
- <link rel="import" href="iron-overlay-backdrop.html">
- <script>
- /**
- * @struct
- * @constructor
- * @private
- */
- Polymer.IronOverlayManagerClass = function() {
- /**
- * Used to keep track of the opened overlays.
- * @private {Array<Element>}
- */
- this._overlays = [];
- /**
- * iframes have a default z-index of 100,
- * so this default should be at least that.
- * @private {number}
- */
- this._minimumZ = 101;
- /**
- * Memoized backdrop element.
- * @private {Element|null}
- */
- this._backdropElement = null;
- // Enable document-wide tap recognizer.
- Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this));
- 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.
- * @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;
- },
- /**
- * Brings the overlay at the specified index to the front.
- * @param {number} i
- * @private
- */
- _bringOverlayAtIndexToFront: function(i) {
- var overlay = this._overlays[i];
- if (!overlay) {
- return;
- }
- var lastI = this._overlays.length - 1;
- var currentOverlay = this._overlays[lastI];
- // Ensure always-on-top overlay stays on top.
- if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
- lastI--;
- }
- // If already the top element, return.
- if (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);
- }
- // Shift other overlays behind the new on top.
- while (i < lastI) {
- this._overlays[i] = this._overlays[i + 1];
- i++;
- }
- this._overlays[lastI] = overlay;
- },
- /**
- * 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);
- }
- },
- /**
- * 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);
- this.trackBackdrop();
- 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 && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
- // 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);
- this.trackBackdrop();
- },
- /**
- * @param {!Element} overlay
- */
- removeOverlay: function(overlay) {
- var i = this._overlays.indexOf(overlay);
- if (i === -1) {
- return;
- }
- this._overlays.splice(i, 1);
- this.trackBackdrop();
- },
- /**
- * Returns the current overlay.
- * @return {Element|undefined}
- */
- currentOverlay: function() {
- var i = this._overlays.length - 1;
- return this._overlays[i];
- },
- /**
- * 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
- */
- ensureMinimumZ: function(minimumZ) {
- this._minimumZ = Math.max(this._minimumZ, minimumZ);
- },
- focusOverlay: function() {
- var current = /** @type {?} */ (this.currentOverlay());
- if (current) {
- current._applyFocus();
- }
- },
- /**
- * Updates the backdrop z-index.
- */
- trackBackdrop: function() {
- var overlay = this._overlayWithBackdrop();
- // Avoid creating the backdrop if there is no overlay with backdrop.
- if (!overlay && !this._backdropElement) {
- return;
- }
- this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
- this.backdropElement.opened = !!overlay;
- },
- /**
- * @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.
- * @return {number}
- */
- backdropZ: function() {
- return this._getZ(this._overlayWithBackdrop()) - 1;
- },
- /**
- * 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.
- * @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 deepest overlay in the path.
- * @param {Array<Element>=} path
- * @return {Element|undefined}
- * @suppress {missingProperties}
- * @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);
- }
- }
- },
- /**
- * Returns if the overlay1 should be behind overlay2.
- * @param {!Element} overlay1
- * @param {!Element} overlay2
- * @return {boolean}
- * @suppress {missingProperties}
- * @private
- */
- _shouldBeBehindOverlay: function(overlay1, overlay2) {
- return !overlay1.alwaysOnTop && overlay2.alwaysOnTop;
- }
- };
- Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
- </script>