OLD | NEW |
1 /** | 1 /** |
2 * @struct | 2 * @struct |
3 * @constructor | 3 * @constructor |
4 */ | 4 */ |
5 Polymer.IronOverlayManagerClass = function() { | 5 Polymer.IronOverlayManagerClass = function() { |
6 this._overlays = []; | 6 this._overlays = []; |
| 7 // Used to keep track of the last focused node before an overlay gets opened
. |
| 8 this._lastFocusedNodes = []; |
| 9 |
7 /** | 10 /** |
8 * iframes have a default z-index of 100, so this default should be at least | 11 * iframes have a default z-index of 100, so this default should be at least |
9 * that. | 12 * that. |
10 * @private {number} | 13 * @private {number} |
11 */ | 14 */ |
12 this._minimumZ = 101; | 15 this._minimumZ = 101; |
13 | 16 |
14 this._backdrops = []; | 17 this._backdrops = []; |
15 } | 18 |
| 19 this._backdropElement = null; |
| 20 Object.defineProperty(this, 'backdropElement', { |
| 21 get: function() { |
| 22 if (!this._backdropElement) { |
| 23 this._backdropElement = document.createElement('iron-overlay-backdrop'
); |
| 24 } |
| 25 return this._backdropElement; |
| 26 }.bind(this) |
| 27 }); |
| 28 |
| 29 /** |
| 30 * The deepest active element. |
| 31 * returns {?Node} element the active element |
| 32 */ |
| 33 this.deepActiveElement = null; |
| 34 Object.defineProperty(this, 'deepActiveElement', { |
| 35 get: function() { |
| 36 var active = document.activeElement; |
| 37 // document.activeElement can be null |
| 38 // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeEleme
nt |
| 39 while (active && active.root && Polymer.dom(active.root).activeElement)
{ |
| 40 active = Polymer.dom(active.root).activeElement; |
| 41 } |
| 42 return active; |
| 43 }.bind(this) |
| 44 }); |
| 45 }; |
| 46 |
| 47 /** |
| 48 * If a node is contained in an overlay. |
| 49 * @private |
| 50 * @param {Node} node |
| 51 * @returns {Boolean} |
| 52 */ |
| 53 Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) { |
| 54 while (node && node !== document.body) { |
| 55 // Use logical parentNode, or native ShadowRoot host. |
| 56 node = Polymer.dom(node).parentNode || node.host; |
| 57 // Check if it is an overlay. |
| 58 if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBe
haviorImpl) !== -1) { |
| 59 return true; |
| 60 } |
| 61 } |
| 62 return false; |
| 63 }; |
16 | 64 |
17 Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, a
boveZ) { | 65 Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, a
boveZ) { |
18 this._setZ(overlay, aboveZ + 2); | 66 this._setZ(overlay, aboveZ + 2); |
19 }; | 67 }; |
20 | 68 |
21 Polymer.IronOverlayManagerClass.prototype._setZ = function(element, z) { | 69 Polymer.IronOverlayManagerClass.prototype._setZ = function(element, z) { |
22 element.style.zIndex = z; | 70 element.style.zIndex = z; |
23 }; | 71 }; |
24 | 72 |
25 /** | 73 /** |
26 * track overlays for z-index and focus managemant | 74 * track overlays for z-index and focus managemant |
27 */ | 75 */ |
28 Polymer.IronOverlayManagerClass.prototype.addOverlay = function(overlay) { | 76 Polymer.IronOverlayManagerClass.prototype.addOverlay = function(overlay) { |
29 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); | 77 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); |
30 this._overlays.push(overlay); | 78 this._overlays.push(overlay); |
31 var newZ = this.currentOverlayZ(); | 79 var newZ = this.currentOverlayZ(); |
32 if (newZ <= minimumZ) { | 80 if (newZ <= minimumZ) { |
33 this._applyOverlayZ(overlay, minimumZ); | 81 this._applyOverlayZ(overlay, minimumZ); |
34 } | 82 } |
| 83 var element = this.deepActiveElement; |
| 84 // If already in other overlay, don't reset focus there. |
| 85 if (this._isChildOfOverlay(element)) { |
| 86 element = null; |
| 87 } |
| 88 this._lastFocusedNodes.push(element); |
35 }; | 89 }; |
36 | 90 |
37 Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) { | 91 Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) { |
38 var i = this._overlays.indexOf(overlay); | 92 var i = this._overlays.indexOf(overlay); |
39 if (i >= 0) { | 93 if (i >= 0) { |
40 this._overlays.splice(i, 1); | 94 this._overlays.splice(i, 1); |
41 this._setZ(overlay, ''); | 95 this._setZ(overlay, ''); |
| 96 |
| 97 var node = this._lastFocusedNodes[i]; |
| 98 // Focus only if still contained in document.body |
| 99 if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deep
Contains(node)) { |
| 100 node.focus(); |
| 101 } |
| 102 this._lastFocusedNodes.splice(i, 1); |
42 } | 103 } |
43 }; | 104 }; |
44 | 105 |
45 Polymer.IronOverlayManagerClass.prototype.currentOverlay = function() { | 106 Polymer.IronOverlayManagerClass.prototype.currentOverlay = function() { |
46 var i = this._overlays.length - 1; | 107 var i = this._overlays.length - 1; |
47 while (this._overlays[i] && !this._overlays[i].opened) { | 108 while (this._overlays[i] && !this._overlays[i].opened) { |
48 --i; | 109 --i; |
49 } | 110 } |
50 return this._overlays[i]; | 111 return this._overlays[i]; |
51 }; | 112 }; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 if (element.opened && element.withBackdrop) { | 147 if (element.opened && element.withBackdrop) { |
87 // no duplicates | 148 // no duplicates |
88 if (index === -1) { | 149 if (index === -1) { |
89 this._backdrops.push(element); | 150 this._backdrops.push(element); |
90 } | 151 } |
91 } else if (index >= 0) { | 152 } else if (index >= 0) { |
92 this._backdrops.splice(index, 1); | 153 this._backdrops.splice(index, 1); |
93 } | 154 } |
94 }; | 155 }; |
95 | 156 |
96 Object.defineProperty(Polymer.IronOverlayManagerClass.prototype, "backdropElem
ent", { | |
97 get: function() { | |
98 if (!this._backdropElement) { | |
99 this._backdropElement = document.createElement('iron-overlay-backdrop'); | |
100 } | |
101 return this._backdropElement; | |
102 } | |
103 }); | |
104 | |
105 Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() { | 157 Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() { |
106 return this._backdrops; | 158 return this._backdrops; |
107 }; | 159 }; |
108 | 160 |
109 /** | 161 /** |
110 * Returns the z-index for the backdrop. | 162 * Returns the z-index for the backdrop. |
111 */ | 163 */ |
112 Polymer.IronOverlayManagerClass.prototype.backdropZ = function() { | 164 Polymer.IronOverlayManagerClass.prototype.backdropZ = function() { |
113 return this._getOverlayZ(this._overlayWithBackdrop()) - 1; | 165 return this._getOverlayZ(this._overlayWithBackdrop()) - 1; |
114 }; | 166 }; |
(...skipping 19 matching lines...) Expand all Loading... |
134 // Check if is a number | 186 // Check if is a number |
135 // Number.isNaN not supported in IE 10+ | 187 // Number.isNaN not supported in IE 10+ |
136 if (z1 === z1) { | 188 if (z1 === z1) { |
137 z = z1; | 189 z = z1; |
138 } | 190 } |
139 } | 191 } |
140 return z; | 192 return z; |
141 }; | 193 }; |
142 | 194 |
143 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); | 195 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); |
OLD | NEW |