iron-overlay-manager.html 3.3 KB
<!--
@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">

<script>

  Polymer.IronOverlayManager = {

    _overlays: [],

    // iframes have a default z-index of 100, so this default should be at least
    // that.
    _minimumZ: 101,

    _backdrops: [],

    _applyOverlayZ: function(overlay, aboveZ) {
      this._setZ(overlay, aboveZ + 2);
    },

    _setZ: function(element, z) {
      element.style.zIndex = z;
    },

    // track overlays for z-index and focus managemant
    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);
      }
    },

    removeOverlay: function(overlay) {
      var i = this._overlays.indexOf(overlay);
      if (i >= 0) {
        this._overlays.splice(i, 1);
        this._setZ(overlay, '');
      }
    },

    currentOverlay: function() {
      var i = this._overlays.length - 1;
      while (this._overlays[i] && !this._overlays[i].opened) {
        --i;
      }
      return this._overlays[i];
    },

    currentOverlayZ: function() {
      var z = this._minimumZ;
      var current = this.currentOverlay();
      if (current) {
        var z1 = window.getComputedStyle(current).zIndex;
        if (!isNaN(z1)) {
          z = Number(z1);
        }
      }
      return z;
    },

    /**
     * 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 = 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();
      }
    },

    trackBackdrop: function(element) {
      // backdrops contains the overlays with a backdrop that are currently
      // visible
      if (element.opened) {
        this._backdrops.push(element);
      } else {
        var index = this._backdrops.indexOf(element);
        if (index >= 0) {
          this._backdrops.splice(index, 1);
        }
      }
    },

    getBackdrops: function() {
      return this._backdrops;
    }

  };

</script>