| OLD | NEW |
| 1 <!-- | 1 <!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --> | 9 --> |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 * @private {number} | 32 * @private {number} |
| 33 */ | 33 */ |
| 34 this._minimumZ = 101; | 34 this._minimumZ = 101; |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * Memoized backdrop element. | 37 * Memoized backdrop element. |
| 38 * @private {Element|null} | 38 * @private {Element|null} |
| 39 */ | 39 */ |
| 40 this._backdropElement = null; | 40 this._backdropElement = null; |
| 41 | 41 |
| 42 // Listen to mousedown or touchstart to be sure to be the first to capture | 42 // Enable document-wide tap recognizer. |
| 43 // clicks outside the overlay. | 43 Polymer.Gestures.add(document, 'tap', null); |
| 44 var clickEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown'; | 44 // Need to have useCapture=true, Polymer.Gestures doesn't offer that. |
| 45 document.addEventListener(clickEvent, this._onCaptureClick.bind(this), true)
; | 45 document.addEventListener('tap', this._onCaptureClick.bind(this), true); |
| 46 document.addEventListener('focus', this._onCaptureFocus.bind(this), true); | 46 document.addEventListener('focus', this._onCaptureFocus.bind(this), true); |
| 47 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true
); | 47 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true
); |
| 48 }; | 48 }; |
| 49 | 49 |
| 50 Polymer.IronOverlayManagerClass.prototype = { | 50 Polymer.IronOverlayManagerClass.prototype = { |
| 51 | 51 |
| 52 constructor: Polymer.IronOverlayManagerClass, | 52 constructor: Polymer.IronOverlayManagerClass, |
| 53 | 53 |
| 54 /** | 54 /** |
| 55 * The shared backdrop element. | 55 * The shared backdrop element. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 * Adds the overlay and updates its z-index if it's opened, or removes it if
it's closed. | 115 * Adds the overlay and updates its z-index if it's opened, or removes it if
it's closed. |
| 116 * Also updates the backdrop z-index. | 116 * Also updates the backdrop z-index. |
| 117 * @param {!Element} overlay | 117 * @param {!Element} overlay |
| 118 */ | 118 */ |
| 119 addOrRemoveOverlay: function(overlay) { | 119 addOrRemoveOverlay: function(overlay) { |
| 120 if (overlay.opened) { | 120 if (overlay.opened) { |
| 121 this.addOverlay(overlay); | 121 this.addOverlay(overlay); |
| 122 } else { | 122 } else { |
| 123 this.removeOverlay(overlay); | 123 this.removeOverlay(overlay); |
| 124 } | 124 } |
| 125 this.trackBackdrop(); | |
| 126 }, | 125 }, |
| 127 | 126 |
| 128 /** | 127 /** |
| 129 * Tracks overlays for z-index and focus management. | 128 * Tracks overlays for z-index and focus management. |
| 130 * Ensures the last added overlay with always-on-top remains on top. | 129 * Ensures the last added overlay with always-on-top remains on top. |
| 131 * @param {!Element} overlay | 130 * @param {!Element} overlay |
| 132 */ | 131 */ |
| 133 addOverlay: function(overlay) { | 132 addOverlay: function(overlay) { |
| 134 var i = this._overlays.indexOf(overlay); | 133 var i = this._overlays.indexOf(overlay); |
| 135 if (i >= 0) { | 134 if (i >= 0) { |
| 136 this._bringOverlayAtIndexToFront(i); | 135 this._bringOverlayAtIndexToFront(i); |
| 136 this.trackBackdrop(); |
| 137 return; | 137 return; |
| 138 } | 138 } |
| 139 var insertionIndex = this._overlays.length; | 139 var insertionIndex = this._overlays.length; |
| 140 var currentOverlay = this._overlays[insertionIndex - 1]; | 140 var currentOverlay = this._overlays[insertionIndex - 1]; |
| 141 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ); | 141 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ); |
| 142 var newZ = this._getZ(overlay); | 142 var newZ = this._getZ(overlay); |
| 143 | 143 |
| 144 // Ensure always-on-top overlay stays on top. | 144 // Ensure always-on-top overlay stays on top. |
| 145 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)
) { | 145 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)
) { |
| 146 // This bumps the z-index of +2. | 146 // This bumps the z-index of +2. |
| 147 this._applyOverlayZ(currentOverlay, minimumZ); | 147 this._applyOverlayZ(currentOverlay, minimumZ); |
| 148 insertionIndex--; | 148 insertionIndex--; |
| 149 // Update minimumZ to match previous overlay's z-index. | 149 // Update minimumZ to match previous overlay's z-index. |
| 150 var previousOverlay = this._overlays[insertionIndex - 1]; | 150 var previousOverlay = this._overlays[insertionIndex - 1]; |
| 151 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ); | 151 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ); |
| 152 } | 152 } |
| 153 | 153 |
| 154 // Update z-index and insert overlay. | 154 // Update z-index and insert overlay. |
| 155 if (newZ <= minimumZ) { | 155 if (newZ <= minimumZ) { |
| 156 this._applyOverlayZ(overlay, minimumZ); | 156 this._applyOverlayZ(overlay, minimumZ); |
| 157 } | 157 } |
| 158 this._overlays.splice(insertionIndex, 0, overlay); | 158 this._overlays.splice(insertionIndex, 0, overlay); |
| 159 | 159 |
| 160 // Get focused node. | 160 // Get focused node. |
| 161 var element = this.deepActiveElement; | 161 var element = this.deepActiveElement; |
| 162 overlay.restoreFocusNode = this._overlayParent(element) ? null : element; | 162 overlay.restoreFocusNode = this._overlayParent(element) ? null : element; |
| 163 this.trackBackdrop(); |
| 163 }, | 164 }, |
| 164 | 165 |
| 165 /** | 166 /** |
| 166 * @param {!Element} overlay | 167 * @param {!Element} overlay |
| 167 */ | 168 */ |
| 168 removeOverlay: function(overlay) { | 169 removeOverlay: function(overlay) { |
| 169 var i = this._overlays.indexOf(overlay); | 170 var i = this._overlays.indexOf(overlay); |
| 170 if (i === -1) { | 171 if (i === -1) { |
| 171 return; | 172 return; |
| 172 } | 173 } |
| 173 this._overlays.splice(i, 1); | 174 this._overlays.splice(i, 1); |
| 174 | 175 |
| 175 var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null; | 176 var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null; |
| 176 overlay.restoreFocusNode = null; | 177 overlay.restoreFocusNode = null; |
| 177 // Focus back only if still contained in document.body | 178 // Focus back only if still contained in document.body |
| 178 if (node && Polymer.dom(document.body).deepContains(node)) { | 179 if (node && Polymer.dom(document.body).deepContains(node)) { |
| 179 node.focus(); | 180 node.focus(); |
| 180 } | 181 } |
| 182 this.trackBackdrop(); |
| 181 }, | 183 }, |
| 182 | 184 |
| 183 /** | 185 /** |
| 184 * Returns the current overlay. | 186 * Returns the current overlay. |
| 185 * @return {Element|undefined} | 187 * @return {Element|undefined} |
| 186 */ | 188 */ |
| 187 currentOverlay: function() { | 189 currentOverlay: function() { |
| 188 var i = this._overlays.length - 1; | 190 var i = this._overlays.length - 1; |
| 189 return this._overlays[i]; | 191 return this._overlays[i]; |
| 190 }, | 192 }, |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 } | 321 } |
| 320 // Use logical parentNode, or native ShadowRoot host. | 322 // Use logical parentNode, or native ShadowRoot host. |
| 321 node = Polymer.dom(node).parentNode || node.host; | 323 node = Polymer.dom(node).parentNode || node.host; |
| 322 } | 324 } |
| 323 }, | 325 }, |
| 324 | 326 |
| 325 /** | 327 /** |
| 326 * Returns the deepest overlay in the path. | 328 * Returns the deepest overlay in the path. |
| 327 * @param {Array<Element>=} path | 329 * @param {Array<Element>=} path |
| 328 * @return {Element|undefined} | 330 * @return {Element|undefined} |
| 331 * @suppress {missingProperties} |
| 329 * @private | 332 * @private |
| 330 */ | 333 */ |
| 331 _overlayInPath: function(path) { | 334 _overlayInPath: function(path) { |
| 332 path = path || []; | 335 path = path || []; |
| 333 for (var i = 0; i < path.length; i++) { | 336 for (var i = 0; i < path.length; i++) { |
| 334 if (path[i]._manager === this) { | 337 if (path[i]._manager === this) { |
| 335 return path[i]; | 338 return path[i]; |
| 336 } | 339 } |
| 337 } | 340 } |
| 338 }, | 341 }, |
| 339 | 342 |
| 340 /** | 343 /** |
| 341 * Ensures the click event is delegated to the right overlay. | 344 * Ensures the click event is delegated to the right overlay. |
| 342 * @param {!Event} event | 345 * @param {!Event} event |
| 343 * @private | 346 * @private |
| 344 */ | 347 */ |
| 345 _onCaptureClick: function(event) { | 348 _onCaptureClick: function(event) { |
| 346 var overlay = /** @type {?} */ (this.currentOverlay()); | 349 var overlay = /** @type {?} */ (this.currentOverlay()); |
| 347 // Check if clicked outside of top overlay. | 350 // Check if clicked outside of top overlay. |
| 348 if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) { | 351 if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) { |
| 349 if (overlay.withBackdrop) { | |
| 350 // There's no need to stop the propagation as the backdrop element | |
| 351 // already got this mousedown/touchstart event. Calling preventDefault | |
| 352 // on this event ensures that click/tap won't be triggered at all. | |
| 353 event.preventDefault(); | |
| 354 } | |
| 355 overlay._onCaptureClick(event); | 352 overlay._onCaptureClick(event); |
| 356 } | 353 } |
| 357 }, | 354 }, |
| 358 | 355 |
| 359 /** | 356 /** |
| 360 * Ensures the focus event is delegated to the right overlay. | 357 * Ensures the focus event is delegated to the right overlay. |
| 361 * @param {!Event} event | 358 * @param {!Event} event |
| 362 * @private | 359 * @private |
| 363 */ | 360 */ |
| 364 _onCaptureFocus: function(event) { | 361 _onCaptureFocus: function(event) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 382 overlay._onCaptureTab(event); | 379 overlay._onCaptureTab(event); |
| 383 } | 380 } |
| 384 } | 381 } |
| 385 }, | 382 }, |
| 386 | 383 |
| 387 /** | 384 /** |
| 388 * Returns if the overlay1 should be behind overlay2. | 385 * Returns if the overlay1 should be behind overlay2. |
| 389 * @param {!Element} overlay1 | 386 * @param {!Element} overlay1 |
| 390 * @param {!Element} overlay2 | 387 * @param {!Element} overlay2 |
| 391 * @return {boolean} | 388 * @return {boolean} |
| 389 * @suppress {missingProperties} |
| 392 * @private | 390 * @private |
| 393 */ | 391 */ |
| 394 _shouldBeBehindOverlay: function(overlay1, overlay2) { | 392 _shouldBeBehindOverlay: function(overlay1, overlay2) { |
| 395 var o1 = /** @type {?} */ (overlay1); | 393 return !overlay1.alwaysOnTop && overlay2.alwaysOnTop; |
| 396 var o2 = /** @type {?} */ (overlay2); | |
| 397 return !o1.alwaysOnTop && o2.alwaysOnTop; | |
| 398 } | 394 } |
| 399 }; | 395 }; |
| 400 | 396 |
| 401 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); | 397 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); |
| 402 </script> | 398 </script> |
| OLD | NEW |