mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update components
This commit is contained in:
parent
feb5e91986
commit
4da1e38cc5
26 changed files with 320 additions and 125 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "iron-overlay-behavior",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Provides a behavior for making an element an overlay",
|
||||
"private": true,
|
||||
|
@ -35,11 +35,11 @@
|
|||
},
|
||||
"ignore": [],
|
||||
"homepage": "https://github.com/polymerelements/iron-overlay-behavior",
|
||||
"_release": "1.4.0",
|
||||
"_release": "1.4.1",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.4.0",
|
||||
"commit": "9731850e81b004723f0c1878a85479f7aa9cfda1"
|
||||
"tag": "v1.4.1",
|
||||
"commit": "4aefb7bc41aecef69022d6435133c430fc52d3ba"
|
||||
},
|
||||
"_source": "git://github.com/polymerelements/iron-overlay-behavior.git",
|
||||
"_target": "^1.0.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "iron-overlay-behavior",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Provides a behavior for making an element an overlay",
|
||||
"private": true,
|
||||
|
|
|
@ -61,6 +61,17 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
</template>
|
||||
</demo-snippet>
|
||||
|
||||
<h3>Use <code>restore-focus-on-close</code> to return the focus to the element that opened the overlay when it gets closed.</h3>
|
||||
<demo-snippet>
|
||||
<template>
|
||||
<button onclick="returnFocus.open()">Overlay that restores focus</button>
|
||||
<simple-overlay id="returnFocus" restore-focus-on-close>
|
||||
<p>Hello world!</p>
|
||||
<button onclick="returnFocus.close()">Close</button>
|
||||
</simple-overlay>
|
||||
</template>
|
||||
</demo-snippet>
|
||||
|
||||
<h3>The child with <code>autofocus</code> gets focused when opening the overlay.</h3>
|
||||
<demo-snippet>
|
||||
<template>
|
||||
|
|
|
@ -128,6 +128,14 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
value: document
|
||||
},
|
||||
|
||||
/**
|
||||
* Set to true to enable restoring of focus when overlay is closed.
|
||||
*/
|
||||
restoreFocusOnClose: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
|
||||
_manager: {
|
||||
type: Object,
|
||||
value: Polymer.IronOverlayManager
|
||||
|
@ -179,7 +187,7 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
* @type {Node}
|
||||
*/
|
||||
get _focusNode() {
|
||||
return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]') || this.__firstFocusableNode || this;
|
||||
return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]') || this;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -235,7 +243,7 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
},
|
||||
|
||||
ready: function() {
|
||||
// with-backdrop need tabindex to be set in order to trap the focus.
|
||||
// with-backdrop needs tabindex to be set in order to trap the focus.
|
||||
// If it is not set, IronOverlayBehavior will set it, and remove it if with-backdrop = false.
|
||||
this.__shouldRemoveTabIndex = false;
|
||||
// Used for wrapping the focus on TAB / Shift+TAB.
|
||||
|
@ -245,7 +253,7 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
|
||||
attached: function() {
|
||||
// Call _openedChanged here so that position can be computed correctly.
|
||||
if (this._callOpenedWhenReady) {
|
||||
if (this.opened) {
|
||||
this._openedChanged();
|
||||
}
|
||||
this._observer = Polymer.dom(this).observeNodes(this._onNodesChange);
|
||||
|
@ -315,7 +323,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
|
||||
// wait to call after ready only if we're initially open
|
||||
if (!this._overlaySetup) {
|
||||
this._callOpenedWhenReady = this.opened;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -552,28 +559,29 @@ context. You should place this element as a child of `<body>` whenever possible.
|
|||
this._focusedChild = nodeToSet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after the `iron-overlay` opens.
|
||||
* @event iron-overlay-opened
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when the `iron-overlay` is canceled, but before it is closed.
|
||||
* Cancel the event to prevent the `iron-overlay` from closing.
|
||||
* @event iron-overlay-canceled
|
||||
* @param {?Event} event The event in case the user pressed ESC or clicked outside the overlay
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired after the `iron-overlay` closes.
|
||||
* @event iron-overlay-closed
|
||||
* @param {{canceled: (boolean|undefined)}} set to the `closingReason` attribute
|
||||
*/
|
||||
};
|
||||
|
||||
/** @polymerBehavior */
|
||||
Polymer.IronOverlayBehavior = [Polymer.IronA11yKeysBehavior, Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
|
||||
|
||||
/**
|
||||
* Fired after the `iron-overlay` opens.
|
||||
* @event iron-overlay-opened
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when the `iron-overlay` is canceled, but before it is closed.
|
||||
* Cancel the event to prevent the `iron-overlay` from closing.
|
||||
* @event iron-overlay-canceled
|
||||
* @param {Event} event The closing of the `iron-overlay` can be prevented
|
||||
* by calling `event.preventDefault()`. The `event.detail` is the original event that originated
|
||||
* the canceling (e.g. ESC keyboard event or click event outside the `iron-overlay`).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired after the `iron-overlay` closes.
|
||||
* @event iron-overlay-closed
|
||||
* @param {{canceled: (boolean|undefined)}} closingReason Contains `canceled` (whether the overlay was canceled).
|
||||
*/
|
||||
|
||||
</script>
|
||||
|
|
|
@ -18,6 +18,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
*/
|
||||
Polymer.IronOverlayManagerClass = function() {
|
||||
this._overlays = [];
|
||||
// Used to keep track of the last focused node before an overlay gets opened.
|
||||
this._lastFocusedNodes = [];
|
||||
|
||||
/**
|
||||
* iframes have a default z-index of 100, so this default should be at least
|
||||
* that.
|
||||
|
@ -36,7 +39,42 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
return this._backdropElement;
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The deepest active element.
|
||||
* returns {?Node} element the active element
|
||||
*/
|
||||
this.deepActiveElement = null;
|
||||
Object.defineProperty(this, 'deepActiveElement', {
|
||||
get: function() {
|
||||
var active = document.activeElement;
|
||||
// document.activeElement can be null
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
|
||||
while (active && active.root && Polymer.dom(active.root).activeElement) {
|
||||
active = Polymer.dom(active.root).activeElement;
|
||||
}
|
||||
return active;
|
||||
}.bind(this)
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* If a node is contained in an overlay.
|
||||
* @private
|
||||
* @param {Node} node
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) {
|
||||
while (node && node !== document.body) {
|
||||
// Use logical parentNode, or native ShadowRoot host.
|
||||
node = Polymer.dom(node).parentNode || node.host;
|
||||
// Check if it is an overlay.
|
||||
if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, aboveZ) {
|
||||
this._setZ(overlay, aboveZ + 2);
|
||||
|
@ -56,6 +94,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
if (newZ <= minimumZ) {
|
||||
this._applyOverlayZ(overlay, minimumZ);
|
||||
}
|
||||
var element = this.deepActiveElement;
|
||||
// If already in other overlay, don't reset focus there.
|
||||
if (this._isChildOfOverlay(element)) {
|
||||
element = null;
|
||||
}
|
||||
this._lastFocusedNodes.push(element);
|
||||
};
|
||||
|
||||
Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) {
|
||||
|
@ -63,6 +107,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
if (i >= 0) {
|
||||
this._overlays.splice(i, 1);
|
||||
this._setZ(overlay, '');
|
||||
|
||||
var node = this._lastFocusedNodes[i];
|
||||
// Focus only if still contained in document.body
|
||||
if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
|
||||
node.focus();
|
||||
}
|
||||
this._lastFocusedNodes.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
<link rel="import" href="../../iron-test-helpers/iron-test-helpers.html">
|
||||
<link rel="import" href="test-overlay.html">
|
||||
<link rel="import" href="test-overlay2.html">
|
||||
<link rel="import" href="test-buttons.html">
|
||||
|
||||
<style is="custom-style">
|
||||
iron-overlay-backdrop {
|
||||
|
@ -112,6 +113,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-buttons id="buttons"></test-buttons>
|
||||
<input id="focusInput" placeholder="focus input">
|
||||
|
||||
<script>
|
||||
function runAfterOpen(overlay, callback) {
|
||||
overlay.addEventListener('iron-overlay-opened', function() {
|
||||
|
@ -453,13 +457,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
assert.equal(focusableNodes[5], Polymer.dom(overlayWithTabIndex).querySelector('.focusable6'));
|
||||
});
|
||||
|
||||
test('first focusable is focused if no [autofocus] node is present', function(done) {
|
||||
runAfterOpen(overlay, function() {
|
||||
assert.equal(Polymer.dom(overlay).querySelector('.focusable1'), document.activeElement, 'focusable1 is focused');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('with-backdrop: TAB & Shift+TAB wrap focus', function(done) {
|
||||
overlay.withBackdrop = true;
|
||||
var focusableNodes = overlay._focusableNodes;
|
||||
|
@ -498,6 +495,109 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
|
||||
});
|
||||
|
||||
suite('Polymer.IronOverlayManager.deepActiveElement', function() {
|
||||
|
||||
test('handles document.body', function () {
|
||||
document.body.focus();
|
||||
assert.equal(Polymer.IronOverlayManager.deepActiveElement, document.body);
|
||||
});
|
||||
|
||||
test('handles light dom', function () {
|
||||
var focusable = document.getElementById('focusInput');
|
||||
focusable.focus();
|
||||
assert.equal(Polymer.IronOverlayManager.deepActiveElement, focusable, 'input is handled');
|
||||
focusable.blur();
|
||||
});
|
||||
|
||||
test('handles shadow dom', function () {
|
||||
var focusable = document.getElementById('buttons').$.button0;
|
||||
focusable.focus();
|
||||
assert.equal(Polymer.IronOverlayManager.deepActiveElement, focusable);
|
||||
focusable.blur();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('restore-focus-on-close', function() {
|
||||
|
||||
var overlay;
|
||||
setup(function () {
|
||||
overlay = fixture('autofocus');
|
||||
overlay.restoreFocusOnClose = true;
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
// No matter what, return the focus to body!
|
||||
document.body.focus();
|
||||
});
|
||||
|
||||
test('does not return focus on close by default (restore-focus-on-close=false)', function(done) {
|
||||
overlay.restoreFocusOnClose = false;
|
||||
var focusable = document.getElementById('focusInput');
|
||||
focusable.focus();
|
||||
runAfterOpen(overlay, function() {
|
||||
runAfterClose(overlay, function() {
|
||||
assert.notEqual(Polymer.IronOverlayManager.deepActiveElement, focusable, 'focus is not restored to focusable');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('overlay returns focus on close', function(done) {
|
||||
var focusable = document.getElementById('focusInput');
|
||||
focusable.focus();
|
||||
runAfterOpen(overlay, function() {
|
||||
runAfterClose(overlay, function() {
|
||||
assert.equal(Polymer.IronOverlayManager.deepActiveElement, focusable, 'focus restored to focusable');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('overlay returns focus on close (ShadowDOM)', function(done) {
|
||||
var focusable = document.getElementById('buttons').$.button0;
|
||||
focusable.focus();
|
||||
runAfterOpen(overlay, function() {
|
||||
runAfterClose(overlay, function() {
|
||||
assert.equal(Polymer.IronOverlayManager.deepActiveElement, focusable, 'focus restored to focusable');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('overlay does not return focus to elements contained in another overlay', function(done) {
|
||||
var overlay2 = fixture('basic');
|
||||
// So it doesn't interfere with focus changes.
|
||||
overlay2.noAutoFocus = true;
|
||||
var focusable = document.createElement('input');
|
||||
runAfterOpen(overlay2,function () {
|
||||
Polymer.dom(overlay2).appendChild(focusable);
|
||||
focusable.focus();
|
||||
runAfterOpen(overlay, function() {
|
||||
runAfterClose(overlay, function() {
|
||||
assert.notEqual(Polymer.IronOverlayManager.deepActiveElement, focusable, 'focus not restored to focusable inside overlay2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('overlay does not return focus to elements that are not in the body anymore', function(done) {
|
||||
var focusable = document.createElement('input');
|
||||
document.body.appendChild(focusable);
|
||||
focusable.focus();
|
||||
var focusSpy = sinon.spy(focusable, 'focus');
|
||||
runAfterOpen(overlay, function() {
|
||||
document.body.removeChild(focusable);
|
||||
runAfterClose(overlay, function() {
|
||||
assert.isFalse(focusSpy.called, 'focus not called');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('overlay with backdrop', function() {
|
||||
var overlay;
|
||||
|
||||
|
@ -548,9 +648,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||
|
||||
test('manager.getBackdrops() immediately updated on opened changes', function() {
|
||||
overlay.opened = true;
|
||||
assert.equal(overlay._manager.getBackdrops().length, 1, 'overlay added to manager backdrops');
|
||||
assert.equal(Polymer.IronOverlayManager.getBackdrops().length, 1, 'overlay added to manager backdrops');
|
||||
overlay.opened = false;
|
||||
assert.equal(overlay._manager.getBackdrops().length, 0, 'overlay removed from manager backdrops');
|
||||
assert.equal(Polymer.IronOverlayManager.getBackdrops().length, 0, 'overlay removed from manager backdrops');
|
||||
});
|
||||
|
||||
test('updating with-backdrop to false closes backdrop', function(done) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue