diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json index 3d86035ba2..2fa5e27ffc 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json @@ -15,12 +15,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.0.23", - "_release": "1.0.23", + "version": "1.0.29", + "_release": "1.0.29", "_resolution": { "type": "version", - "tag": "1.0.23", - "commit": "1e7c56cf54a657d72d35d36f37937231942a2685" + "tag": "1.0.29", + "commit": "2e60e59d116fee68281235ba19f1e74073565c50" }, "_source": "git://github.com/MediaBrowser/emby-webcomponents.git", "_target": "~1.0.0", diff --git a/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js b/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js new file mode 100644 index 0000000000..e2ecb68a1b --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js @@ -0,0 +1,415 @@ +define([], function () { + + function autoFocus(view, defaultToFirst) { + + var element = view.querySelector('*[autofocus]'); + if (element) { + focus(element); + } else if (defaultToFirst !== false) { + element = getFocusableElements(view)[0]; + + if (element) { + focus(element); + } + } + } + + function focus(element) { + + var tagName = element.tagName; + if (tagName == 'PAPER-INPUT' || tagName == 'PAPER-DROPDOWN-MENU' || tagName == 'EMBY-DROPDOWN-MENU') { + element = element.querySelector('input'); + } + + element.focus(); + } + + var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A', 'PAPER-BUTTON', 'PAPER-INPUT', 'PAPER-TEXTAREA', 'PAPER-ICON-BUTTON', 'PAPER-FAB', 'PAPER-ICON-ITEM', 'PAPER-MENU-ITEM', 'PAPER-DROPDOWN-MENU', 'EMBY-DROPDOWN-MENU']; + var focusableContainerTagNames = ['BODY', 'PAPER-DIALOG']; + var focusableQuery = focusableTagNames.join(',') + ',.focusable'; + + function isFocusable(elem) { + + if (focusableTagNames.indexOf(elem.tagName) != -1) { + return true; + } + + if (elem.classList && elem.classList.contains('focusable')) { + return true; + } + + return false; + } + + function focusableParent(elem) { + + while (!isFocusable(elem)) { + elem = elem.parentNode; + + if (!elem) { + return null; + } + } + + return elem; + } + + function isFocusableElementValid(elem) { + + if (elem.disabled) { + return false; + } + + if (elem.getAttribute('tabindex') == "-1") { + return false; + } + + // http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom + if (elem.offsetParent === null) { + return false; + } + + return true; + } + + function getFocusableElements(parent) { + var elems = (parent || document).querySelectorAll(focusableQuery); + var focusableElements = []; + + for (var i = 0, length = elems.length; i < length; i++) { + + var elem = elems[i]; + + if (isFocusableElementValid(elem)) { + focusableElements.push(elem); + } + } + + return focusableElements; + } + + function isFocusContainer(elem, direction) { + + if (focusableContainerTagNames.indexOf(elem.tagName) != -1) { + return true; + } + + if (direction < 2) { + if (elem.classList.contains('focuscontainer-x')) { + return true; + } + } + else if (direction == 3) { + if (elem.classList.contains('focuscontainer-down')) { + return true; + } + } + + return false; + } + + function getFocusContainer(elem, direction) { + while (!isFocusContainer(elem, direction)) { + elem = elem.parentNode; + + if (!elem) { + return document.body; + } + } + + return elem; + } + + function getOffset(elem, doc) { + + var box = { top: 0, left: 0 }; + + if (!doc) { + return box; + } + + var docElem = doc.documentElement; + + // Support: BlackBerry 5, iOS 3 (original iPhone) + // If we don't have gBCR, just use 0,0 rather than error + if (elem.getBoundingClientRect) { + box = elem.getBoundingClientRect(); + } + var win = doc.defaultView; + return { + top: box.top + win.pageYOffset - docElem.clientTop, + left: box.left + win.pageXOffset - docElem.clientLeft + }; + } + + function getViewportBoundingClientRect(elem) { + + var doc = elem.ownerDocument; + var offset = getOffset(elem, doc); + var win = doc.defaultView; + + var posY = offset.top - win.pageXOffset; + var posX = offset.left - win.pageYOffset; + + var width = elem.offsetWidth; + var height = elem.offsetHeight; + + return { + left: posX, + top: posY, + width: width, + height: height, + right: posX + width, + bottom: posY + height + }; + var scrollLeft = (((t = document.documentElement) || (t = document.body.parentNode)) + && typeof t.scrollLeft == 'number' ? t : document.body).scrollLeft; + + var scrollTop = (((t = document.documentElement) || (t = document.body.parentNode)) + && typeof t.scrollTop == 'number' ? t : document.body).scrollTop; + } + + function nav(activeElement, direction) { + + activeElement = activeElement || document.activeElement; + + if (activeElement) { + activeElement = focusableParent(activeElement); + } + + var container = activeElement ? getFocusContainer(activeElement, direction) : document.body; + + if (!activeElement) { + autoFocus(container, true); + return; + } + + var focusableContainer = parentWithClass(activeElement, 'focusable'); + + var rect = getViewportBoundingClientRect(activeElement); + var focusableElements = []; + + var focusable = container.querySelectorAll(focusableQuery); + for (var i = 0, length = focusable.length; i < length; i++) { + var curr = focusable[i]; + + if (curr == activeElement) { + continue; + } + // Don't refocus into the same container + if (curr == focusableContainer) { + continue; + } + + if (!isFocusableElementValid(curr)) { + continue; + } + + var elementRect = getViewportBoundingClientRect(curr); + + switch (direction) { + + case 0: + // left + if (elementRect.left >= rect.left) { + continue; + } + if (elementRect.right == rect.right) { + continue; + } + break; + case 1: + // right + if (elementRect.right <= rect.right) { + continue; + } + if (elementRect.left == rect.left) { + continue; + } + break; + case 2: + // up + if (elementRect.top >= rect.top) { + continue; + } + if (elementRect.bottom >= rect.bottom) { + continue; + } + break; + case 3: + // down + if (elementRect.bottom <= rect.bottom) { + continue; + } + if (elementRect.top <= rect.top) { + continue; + } + break; + default: + break; + } + focusableElements.push({ + element: curr, + clientRect: elementRect + }); + } + + var nearest = getNearestElements(focusableElements, rect, direction); + + if (nearest.length) { + + var nearestElement = nearest[0].node; + + // See if there's a focusable container, and if so, send the focus command to that + var nearestElementFocusableParent = parentWithClass(nearestElement, 'focusable'); + if (nearestElementFocusableParent && nearestElementFocusableParent != nearestElement && activeElement) { + if (parentWithClass(activeElement, 'focusable') != nearestElementFocusableParent) { + nearestElement = nearestElementFocusableParent; + } + } + + focus(nearestElement); + } + } + + function parentWithClass(elem, className) { + + while (!elem.classList || !elem.classList.contains(className)) { + elem = elem.parentNode; + + if (!elem) { + return null; + } + } + + return elem; + } + + function getNearestElements(elementInfos, options, direction) { + + // Get elements and work out x/y points + var cache = [], + point1x = parseFloat(options.left) || 0, + point1y = parseFloat(options.top) || 0, + point2x = parseFloat(point1x + options.width - 1) || point1x, + point2y = parseFloat(point1y + options.height - 1) || point1y, + // Shortcuts to help with compression + min = Math.min, + max = Math.max; + + var sourceMidX = options.left + (options.width / 2); + var sourceMidY = options.top + (options.height / 2); + + // Loop through all elements and check their positions + for (var i = 0, length = elementInfos.length; i < length; i++) { + + var elementInfo = elementInfos[i]; + var elem = elementInfo.element; + + var off = elementInfo.clientRect, + x = off.left, + y = off.top, + x2 = x + off.width - 1, + y2 = y + off.height - 1, + maxX1 = max(x, point1x), + minX2 = min(x2, point2x), + maxY1 = max(y, point1y), + minY2 = min(y2, point2y), + intersectX = minX2 >= maxX1, + intersectY = minY2 >= maxY1; + + var midX = off.left + (off.width / 2); + var midY = off.top + (off.height / 2); + + var distX; + var distY; + + switch (direction) { + + case 0: + // left + distX = intersectX ? 0 : Math.abs(point1x - x2); + distY = intersectY ? 0 : Math.abs(sourceMidY - midY); + break; + case 1: + // right + distX = intersectX ? 0 : Math.abs(x - point2x); + distY = intersectY ? 0 : Math.abs(sourceMidY - midY); + break; + case 2: + // up + distY = intersectY ? 0 : Math.abs(point1y - y2); + distX = intersectX ? 0 : Math.abs(sourceMidX - midX); + break; + case 3: + // down + distY = intersectY ? 0 : Math.abs(y - point2y); + distX = intersectX ? 0 : Math.abs(sourceMidX - midX); + break; + default: + break; + } + + var distT = Math.sqrt(distX * distX + distY * distY); + + cache.push({ + node: elem, + distX: distX, + distY: distY, + distT: distT + }); + } + + cache.sort(sortNodesT); + //if (direction < 2) { + // cache.sort(sortNodesX); + //} else { + // cache.sort(sortNodesY); + //} + + return cache; + } + + function sortNodesX(a, b) { + var result = a.distX - b.distX; + + if (result == 0) { + return a.distY - b.distY; + } + + return result; + } + + function sortNodesT(a, b) { + return a.distT - b.distT; + } + + function sortNodesY(a, b) { + var result = a.distY - b.distY; + + if (result == 0) { + return a.distX - b.distX; + } + + return result; + } + + return { + autoFocus: autoFocus, + focus: focus, + focusableParent: focusableParent, + getFocusableElements: getFocusableElements, + moveLeft: function (sourceElement) { + nav(sourceElement, 0); + }, + moveRight: function (sourceElement) { + nav(sourceElement, 1); + }, + moveUp: function (sourceElement) { + nav(sourceElement, 2); + }, + moveDown: function (sourceElement) { + nav(sourceElement, 3); + } + }; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.css b/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.css new file mode 100644 index 0000000000..cf54eccfd7 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.css @@ -0,0 +1,28 @@ +.paperDialog { + margin: 0; + top: 0; + left: 0; + right: 0; + bottom: 0; + position: fixed; + max-width: none !important; + max-height: none !important; + display: flex; + align-items: center; + justify-content: center; +} + + .paperDialog.scrollY { + overflow-y: auto; + -webkit-overflow-scrolling: touch; + overflow-x: hidden; + } + + .paperDialog.hiddenScroll::-webkit-scrollbar { + display: none; + } + + .paperDialog.hiddenScroll { + -ms-overflow-style: none; + overflow: -moz-scrollbars-none; + } \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.js b/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.js new file mode 100644 index 0000000000..2c064ead86 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/paperdialoghelper/paperdialoghelper.js @@ -0,0 +1,188 @@ +define(['historyManager', 'focusManager', 'performanceManager', 'browser', 'paper-dialog', 'scale-up-animation', 'fade-out-animation', 'fade-in-animation', 'css!./paperdialoghelper.css'], function (historyManager, focusManager, performanceManager, browser) { + + function paperDialogHashHandler(dlg, hash, resolve, lockDocumentScroll) { + + var self = this; + self.originalUrl = window.location.href; + var activeElement = document.activeElement; + + function onHashChange(e) { + + var isBack = self.originalUrl == window.location.href; + + if (isBack || !dlg.opened) { + window.removeEventListener('popstate', onHashChange); + } + + if (isBack) { + self.closedByBack = true; + dlg.close(); + } + } + + function onDialogClosed() { + + if (lockDocumentScroll !== false) { + // TODO + //Dashboard.onPopupClose(); + } + + window.removeEventListener('popstate', onHashChange); + + if (!self.closedByBack) { + var state = history.state || {}; + if (state.dialogId == hash) { + history.back(); + } + } + + activeElement.focus(); + + if (dlg.getAttribute('data-removeonclose') == 'true') { + dlg.parentNode.removeChild(dlg); + } + + //resolve(); + // if we just called history.back(), then use a timeout to allow the history events to fire first + setTimeout(function () { + resolve({ + element: dlg, + closedByBack: self.closedByBack + }); + }, 1); + } + + dlg.addEventListener('iron-overlay-closed', onDialogClosed); + dlg.open(); + + if (lockDocumentScroll !== false) { + // TODO + //Dashboard.onPopupOpen(); + } + + historyManager.pushState({ dialogId: hash }, "Dialog", hash); + + window.addEventListener('popstate', onHashChange); + } + + function open(dlg) { + + return new Promise(function (resolve, reject) { + + new paperDialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve); + }); + } + + function close(dlg) { + + if (dlg.opened) { + history.back(); + } + } + + function onDialogOpened(e) { + + focusManager.autoFocus(e.target); + } + + function createDialog(options) { + + options = options || {}; + + var dlg = document.createElement('paper-dialog'); + + dlg.setAttribute('with-backdrop', 'with-backdrop'); + dlg.setAttribute('role', 'alertdialog'); + + // without this safari will scroll the background instead of the dialog contents + // but not needed here since this is already on top of an existing dialog + // but skip it in IE because it's causing the entire browser to hang + // Also have to disable for firefox because it's causing select elements to not be clickable + if (!browser.msie && !browser.firefox && options.modal !== false) { + dlg.setAttribute('modal', 'modal'); + } + + // seeing max call stack size exceeded in the debugger with this + dlg.setAttribute('noAutoFocus', 'noAutoFocus'); + + var defaultEntryAnimation = performanceManager.getAnimationPerformance() <= 1 ? 'fade-in-animation' : 'scale-up-animation'; + dlg.entryAnimation = options.entryAnimation || defaultEntryAnimation; + dlg.exitAnimation = 'fade-out-animation'; + + dlg.animationConfig = { + // scale up + 'entry': { + name: options.entryAnimation || 'scale-up-animation', + node: dlg, + timing: { duration: options.entryAnimationDuration || 300, easing: 'ease-out' } + }, + // fade out + 'exit': { + name: 'fade-out-animation', + node: dlg, + timing: { duration: options.exitAnimationDuration || 400, easing: 'ease-in' } + } + }; + + dlg.classList.add('paperDialog'); + + dlg.classList.add('scrollY'); + + // TODO: Don't hide for mouse? + dlg.classList.add('hiddenScroll'); + + if (options.removeOnClose) { + dlg.setAttribute('data-removeonclose', 'true'); + } + + dlg.addEventListener('iron-overlay-opened', onDialogOpened); + + return dlg; + } + + function positionTo(dlg, elem) { + + var windowHeight = $(window).height(); + + // If the window height is under a certain amount, don't bother trying to position + // based on an element. + if (windowHeight >= 540) { + + var pos = $(elem).offset(); + + pos.top += elem.offsetHeight / 2; + pos.left += elem.offsetWidth / 2; + + // Account for margins + pos.top -= 24; + pos.left -= 24; + + // Account for popup size - we can't predict this yet so just estimate + pos.top -= $(dlg).height() / 2; + pos.left -= $(dlg).width() / 2; + + // Account for scroll position + pos.top -= $(window).scrollTop(); + pos.left -= $(window).scrollLeft(); + + // Avoid showing too close to the bottom + pos.top = Math.min(pos.top, windowHeight - 300); + pos.left = Math.min(pos.left, $(window).width() - 300); + + // Do some boundary checking + pos.top = Math.max(pos.top, 0); + pos.left = Math.max(pos.left, 0); + + dlg.style.position = 'fixed'; + dlg.style.left = pos.left + 'px'; + dlg.style.top = pos.top + 'px'; + } + } + + return { + open: open, + close: close, + createDialog: createDialog, + positionTo: positionTo + }; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/performancemanager.js b/dashboard-ui/bower_components/emby-webcomponents/performancemanager.js new file mode 100644 index 0000000000..a9dafe94ac --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/performancemanager.js @@ -0,0 +1,15 @@ +define(['browser'], function (browser) { + + function getAnimationPerformance() { + + if (browser.mobile) { + return 1; + } + + return 5; + } + + return { + getAnimationPerformance: getAnimationPerformance + }; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/iron-behaviors/.bower.json b/dashboard-ui/bower_components/iron-behaviors/.bower.json index db08f2170c..17f68b3351 100644 --- a/dashboard-ui/bower_components/iron-behaviors/.bower.json +++ b/dashboard-ui/bower_components/iron-behaviors/.bower.json @@ -29,14 +29,14 @@ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "ignore": [], - "homepage": "https://github.com/PolymerElements/iron-behaviors", + "homepage": "https://github.com/polymerelements/iron-behaviors", "_release": "1.0.12", "_resolution": { "type": "version", "tag": "v1.0.12", "commit": "657f526a2382a659cdf4e13be87ecc89261588a3" }, - "_source": "git://github.com/PolymerElements/iron-behaviors.git", + "_source": "git://github.com/polymerelements/iron-behaviors.git", "_target": "^1.0.0", - "_originalSource": "PolymerElements/iron-behaviors" + "_originalSource": "polymerelements/iron-behaviors" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/.bower.json b/dashboard-ui/bower_components/iron-overlay-behavior/.bower.json index 77b8d27811..fb63745b7a 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/.bower.json +++ b/dashboard-ui/bower_components/iron-overlay-behavior/.bower.json @@ -1,6 +1,6 @@ { "name": "iron-overlay-behavior", - "version": "1.1.2", + "version": "1.2.0", "license": "http://polymer.github.io/LICENSE.txt", "description": "Provides a behavior for making an element an overlay", "private": true, @@ -29,16 +29,16 @@ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "polymer/web-component-tester#^3.4.0", + "web-component-tester": "^4.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "ignore": [], "homepage": "https://github.com/polymerelements/iron-overlay-behavior", - "_release": "1.1.2", + "_release": "1.2.0", "_resolution": { "type": "version", - "tag": "v1.1.2", - "commit": "40e39a971474f48f5c2c8ee7b8568a0ad5426bd8" + "tag": "v1.2.0", + "commit": "1d8e1d29c601add9c135e5103c4d1d0d652dd957" }, "_source": "git://github.com/polymerelements/iron-overlay-behavior.git", "_target": "^1.0.0", diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/.travis.yml b/dashboard-ui/bower_components/iron-overlay-behavior/.travis.yml index 8bc31dc876..3493d3a9f1 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/.travis.yml +++ b/dashboard-ui/bower_components/iron-overlay-behavior/.travis.yml @@ -1,22 +1,25 @@ language: node_js sudo: false before_script: - - npm install web-component-tester - - npm install bower - - 'export PATH=$PWD/node_modules/.bin:$PATH' + - npm install -g bower polylint web-component-tester - bower install + - polylint env: global: - secure: H8AA9JkWfG/vc3MiimoIoYi45KD10hKzitLJnExkomgzFI/f5o9SGtwjCii5P8Kvf4xndftDjYwRgbYyJpSg0IJeq8rm1WS89cY8O6/1dlI/tK1j5xbVRrhqmRQncxUb3K4MAT6Z9br1jwEeamRa+NKmq+v+VEpQY5vwuQ/BHJw= - secure: EaE1AUVgWyn0Y6kqkb54z5r39RvTJzAOmeM0lRl7wXzr5k0mq3VGlxTksJqCVd1PdJESXEhy8eldBnlkwZir/imDTNQxKm13k7ZiFC0000XAzpLZElkH2cLlYCRWcuM+vS7dA9hytV0UcGK2VGqbxfpcesB20dPSneDEUuc5X64= -node_js: 4 + - CXX=g++-4.8 +node_js: stable addons: firefox: latest apt: sources: - google-chrome + - ubuntu-toolchain-r-test packages: - google-chrome-stable + - g++-4.8 + sauce_connect: true script: - xvfb-run wct - "if [ \"${TRAVIS_PULL_REQUEST}\" = \"false\" ]; then wct -s 'default'; fi" diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/bower.json b/dashboard-ui/bower_components/iron-overlay-behavior/bower.json index a21be7fe4c..e6f916d116 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/bower.json +++ b/dashboard-ui/bower_components/iron-overlay-behavior/bower.json @@ -1,6 +1,6 @@ { "name": "iron-overlay-behavior", - "version": "1.1.2", + "version": "1.2.0", "license": "http://polymer.github.io/LICENSE.txt", "description": "Provides a behavior for making an element an overlay", "private": true, @@ -29,7 +29,7 @@ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "polymer/web-component-tester#^3.4.0", + "web-component-tester": "^4.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "ignore": [] diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-backdrop.html b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-backdrop.html index 5682c28505..5a5e24b5eb 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-backdrop.html +++ b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-backdrop.html @@ -85,13 +85,18 @@ Custom property | Description | Default }, + listeners: { + 'transitionend' : '_onTransitionend' + }, + /** * Appends the backdrop to document body and sets its `z-index` to be below the latest overlay. */ prepare: function() { + // Always update z-index + this.style.zIndex = this._manager.backdropZ(); if (!this.parentNode) { Polymer.dom(document.body).appendChild(this); - this.style.zIndex = this._manager.currentOverlayZ() - 1; } }, @@ -109,9 +114,14 @@ Custom property | Description | Default * Hides the backdrop if needed. */ close: function() { - // only need to make the backdrop invisible if this is called by the last overlay with a backdrop - if (this._manager.getBackdrops().length < 2) { + // Always update z-index + this.style.zIndex = this._manager.backdropZ(); + // close only if no element with backdrop is left + if (this._manager.getBackdrops().length === 0) { this._setOpened(false); + // complete() will be called after the transition is done. + // If animations are disabled via custom-styles, user is expected to call + // complete() after close() } }, @@ -123,6 +133,12 @@ Custom property | Description | Default if (this._manager.getBackdrops().length === 0 && this.parentNode) { Polymer.dom(this.parentNode).removeChild(this); } + }, + + _onTransitionend: function (event) { + if (event && event.target === this) { + this.complete(); + } } }); diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-behavior.html b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-behavior.html index c18cec68fb..afa489f537 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-behavior.html +++ b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-behavior.html @@ -80,8 +80,8 @@ context. You should place this element as a child of `
` whenever possible. * Set to true to display a backdrop behind the overlay. */ withBackdrop: { - type: Boolean, - value: false + observer: '_withBackdropChanged', + type: Boolean }, /** @@ -148,17 +148,13 @@ context. You should place this element as a child of `` whenever possible. * @type Node */ get backdropElement() { - return this._backdrop; + return this._manager.backdropElement; }, get _focusNode() { return Polymer.dom(this).querySelector('[autofocus]') || this; }, - registered: function() { - this._backdrop = document.createElement('iron-overlay-backdrop'); - }, - ready: function() { this._ensureSetup(); }, @@ -172,7 +168,7 @@ context. You should place this element as a child of `` whenever possible. detached: function() { this.opened = false; - this._completeBackdrop(); + this._manager.trackBackdrop(this); this._manager.removeOverlay(this); }, @@ -180,6 +176,7 @@ context. You should place this element as a child of `` whenever possible. * Toggle the opened state of the overlay. */ toggle: function() { + this._setCanceled(false); this.opened = !this.opened; }, @@ -187,16 +184,16 @@ context. You should place this element as a child of `` whenever possible. * Open the overlay. */ open: function() { + this._setCanceled(false); this.opened = true; - this.closingReason = {canceled: false}; }, /** * Close the overlay. */ close: function() { - this.opened = false; this._setCanceled(false); + this.opened = false; }, /** @@ -208,8 +205,8 @@ context. You should place this element as a child of `` whenever possible. return; } - this.opened = false; this._setCanceled(true); + this.opened = false; }, _ensureSetup: function() { @@ -226,6 +223,7 @@ context. You should place this element as a child of `` whenever possible. this.removeAttribute('aria-hidden'); } else { this.setAttribute('aria-hidden', 'true'); + Polymer.dom(this).unobserveNodes(this._observer); } // wait to call after ready only if we're initially open @@ -233,30 +231,32 @@ context. You should place this element as a child of `` whenever possible. this._callOpenedWhenReady = this.opened; return; } - if (this._openChangedAsync) { - this.cancelAsync(this._openChangedAsync); - } - this._toggleListeners(); + this._manager.trackBackdrop(this); if (this.opened) { this._prepareRenderOpened(); } - // async here to allow overlay layer to become visible. + if (this._openChangedAsync) { + this.cancelAsync(this._openChangedAsync); + } + // Async here to allow overlay layer to become visible, and to avoid + // listeners to immediately close via a click. this._openChangedAsync = this.async(function() { // overlay becomes visible here this.style.display = ''; - // force layout to ensure transitions will go - /** @suppress {suspiciousCode} */ this.offsetWidth; + // Force layout to ensure transition will go. Set offsetWidth to itself + // so that compilers won't remove it. + this.offsetWidth = this.offsetWidth; if (this.opened) { this._renderOpened(); } else { this._renderClosed(); } + this._toggleListeners(); this._openChangedAsync = null; - }); - + }, 1); }, _canceledChanged: function() { @@ -264,6 +264,21 @@ context. You should place this element as a child of `` whenever possible. this.closingReason.canceled = this.canceled; }, + _withBackdropChanged: function() { + if (this.opened) { + this._manager.trackBackdrop(this); + if (this.withBackdrop) { + this.backdropElement.prepare(); + // Give time to be added to document. + this.async(function(){ + this.backdropElement.open(); + }, 1); + } else { + this.backdropElement.close(); + } + } + }, + _toggleListener: function(enable, node, event, boundListener, capture) { if (enable) { // enable document-wide tap recognizer @@ -280,30 +295,22 @@ context. You should place this element as a child of `` whenever possible. } }, - _toggleListeners: function() { - if (this._toggleListenersAsync) { - this.cancelAsync(this._toggleListenersAsync); - } - // async so we don't auto-close immediately via a click. - this._toggleListenersAsync = this.async(function() { - this._toggleListener(this.opened, document, 'tap', this._boundOnCaptureClick, true); - this._toggleListener(this.opened, document, 'keydown', this._boundOnCaptureKeydown, true); - this._toggleListenersAsync = null; - }, 1); + _toggleListeners: function () { + this._toggleListener(this.opened, document, 'tap', this._boundOnCaptureClick, true); + this._toggleListener(this.opened, document, 'keydown', this._boundOnCaptureKeydown, true); }, // tasks which must occur before opening; e.g. making the element visible _prepareRenderOpened: function() { this._manager.addOverlay(this); - if (this.withBackdrop) { - this.backdropElement.prepare(); - this._manager.trackBackdrop(this); - } - this._preparePositioning(); this.fit(); this._finishPositioning(); + + if (this.withBackdrop) { + this.backdropElement.prepare(); + } }, // tasks which cause the overlay to actually open; typically play an @@ -322,52 +329,24 @@ context. You should place this element as a child of `` whenever possible. this._finishRenderClosed(); }, - _onTransitionend: function(event) { - // make sure this is our transition event. - if (event && event.target !== this) { - return; - } - if (this.opened) { - this._finishRenderOpened(); - } else { - this._finishRenderClosed(); - } - }, - _finishRenderOpened: function() { // focus the child node with [autofocus] - if (!this.noAutoFocus) { - this._focusNode.focus(); - } + this._applyFocus(); + this._observer = Polymer.dom(this).observeNodes(this.notifyResize); this.fire('iron-overlay-opened'); - - this._squelchNextResize = true; - this.async(this.notifyResize); }, _finishRenderClosed: function() { // hide the overlay and remove the backdrop this.resetFit(); this.style.display = 'none'; - this._completeBackdrop(); this._manager.removeOverlay(this); - this._focusNode.blur(); - // focus the next overlay, if there is one - this._manager.focusOverlay(); + this._applyFocus(); + this.notifyResize(); this.fire('iron-overlay-closed', this.closingReason); - - this._squelchNextResize = true; - this.async(this.notifyResize); - }, - - _completeBackdrop: function() { - if (this.withBackdrop) { - this._manager.trackBackdrop(this); - this.backdropElement.complete(); - } }, _preparePositioning: function() { @@ -396,8 +375,8 @@ context. You should place this element as a child of `` whenever possible. }, _onCaptureClick: function(event) { - if (!this.noCancelOnOutsideClick && - this._manager.currentOverlay() === this && + if (this._manager.currentOverlay() === this && + !this.noCancelOnOutsideClick && Polymer.dom(event).path.indexOf(this) === -1) { this.cancel(); } @@ -405,18 +384,14 @@ context. You should place this element as a child of `` whenever possible. _onCaptureKeydown: function(event) { var ESC = 27; - if (!this.noCancelOnEscKey && (event.keyCode === ESC)) { + if (this._manager.currentOverlay() === this && + !this.noCancelOnEscKey && + event.keyCode === ESC) { this.cancel(); - event.stopPropagation(); - event.stopImmediatePropagation(); } }, _onIronResize: function() { - if (this._squelchNextResize) { - this._squelchNextResize = false; - return; - } if (this.opened) { this.refit(); } diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-manager.html b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-manager.html index c4fea621de..7eeb13d087 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-manager.html +++ b/dashboard-ui/bower_components/iron-overlay-behavior/iron-overlay-manager.html @@ -12,104 +12,148 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN diff --git a/dashboard-ui/bower_components/iron-overlay-behavior/test/index.html b/dashboard-ui/bower_components/iron-overlay-behavior/test/index.html index 9041313cfc..c25fcbf9ad 100644 --- a/dashboard-ui/bower_components/iron-overlay-behavior/test/index.html +++ b/dashboard-ui/bower_components/iron-overlay-behavior/test/index.html @@ -1,5 +1,4 @@ - - - - +-->