1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

render ssa/ass subs in browser

This commit is contained in:
Luke Pulverenti 2016-04-04 21:23:42 -04:00
parent 3c2d0cd3a1
commit cc2c794ad0
26 changed files with 10493 additions and 138 deletions

View file

@ -1,6 +1,6 @@
{
"name": "iron-overlay-behavior",
"version": "1.6.1",
"version": "1.6.2",
"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.6.1",
"_release": "1.6.2",
"_resolution": {
"type": "version",
"tag": "v1.6.1",
"commit": "34f2ed86b2e46f2827dd09594ae99acff0f28029"
"tag": "v1.6.2",
"commit": "be4e703b6894af6d4013a8a9f514a384ee91e2db"
},
"_source": "git://github.com/polymerelements/iron-overlay-behavior.git",
"_target": "^1.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "iron-overlay-behavior",
"version": "1.6.1",
"version": "1.6.2",
"license": "http://polymer.github.io/LICENSE.txt",
"description": "Provides a behavior for making an element an overlay",
"private": true,

View file

@ -15,6 +15,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<link rel="import" href="iron-overlay-manager.html">
<script>
// IIFE to help scripts concatenation.
(function() {
'use strict';
/**
Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or shown, and displays
@ -233,6 +236,10 @@ context. You should place this element as a child of `<body>` whenever possible.
this.__shouldRemoveTabIndex = false;
// Used for wrapping the focus on TAB / Shift+TAB.
this.__firstFocusableNode = this.__lastFocusableNode = null;
// Used for requestAnimationFrame when opened changes.
this.__openChangedAsync = null;
// Used for requestAnimationFrame when iron-resize is fired.
this.__onIronResizeAsync = null;
this._ensureSetup();
},
@ -317,26 +324,22 @@ context. You should place this element as a child of `<body>` whenever possible.
this.__isAnimating = true;
// requestAnimationFrame for non-blocking rendering
if (this.__openChangedAsync) {
cancelAnimationFrame(this.__openChangedAsync);
}
if (this.opened) {
this._prepareRenderOpened();
}
if (this._openChangedAsync) {
this.cancelAsync(this._openChangedAsync);
}
// Async here to allow overlay layer to become visible.
this._openChangedAsync = this.async(function() {
// overlay becomes visible here
this.style.display = '';
// 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();
if (this.withBackdrop) {
this.backdropElement.prepare();
}
this._openChangedAsync = null;
});
this.__openChangedAsync = requestAnimationFrame(function() {
this.__openChangedAsync = null;
this._prepareRenderOpened();
this._renderOpened();
}.bind(this));
} else {
this._renderClosed();
}
},
_canceledChanged: function() {
@ -379,10 +382,6 @@ context. You should place this element as a child of `<body>` whenever possible.
this.refit();
this._finishPositioning();
if (this.withBackdrop) {
this.backdropElement.prepare();
}
// Safari will apply the focus to the autofocus element when displayed for the first time,
// so we blur it. Later, _applyFocus will set the focus if necessary.
if (this.noAutoFocus && document.activeElement === this._focusNode) {
@ -432,6 +431,8 @@ context. You should place this element as a child of `<body>` whenever possible.
_finishRenderClosed: function() {
// Hide the overlay and remove the backdrop.
this.style.display = 'none';
// Reset z-index only at the end of the animation.
this.style.zIndex = '';
this._applyFocus();
@ -447,12 +448,18 @@ context. You should place this element as a child of `<body>` whenever possible.
},
_finishPositioning: function() {
// First, make it invisible & reactivate animations.
this.style.display = 'none';
this.style.transform = this.style.webkitTransform = '';
// Force layout layout to avoid application of transform.
// Set offsetWidth to itself so that compilers won't remove it.
this.offsetWidth = this.offsetWidth;
// Force reflow before re-enabling animations so that they don't start.
// Set scrollTop to itself so that Closure Compiler doesn't remove this.
this.scrollTop = this.scrollTop;
this.style.transition = this.style.webkitTransition = '';
this.style.transform = this.style.webkitTransform = '';
// Now that animations are enabled, make it visible again
this.style.display = '';
// Force reflow, so that following animations are properly started.
// Set scrollTop to itself so that Closure Compiler doesn't remove this.
this.scrollTop = this.scrollTop;
},
/**
@ -535,12 +542,15 @@ context. You should place this element as a child of `<body>` whenever possible.
* @protected
*/
_onIronResize: function() {
if (this.__isAnimating) {
return;
if (this.__onIronResizeAsync) {
cancelAnimationFrame(this.__onIronResizeAsync);
this.__onIronResizeAsync = null;
}
if (this.opened) {
this.refit();
if (this.opened && !this.__isAnimating) {
this.__onIronResizeAsync = requestAnimationFrame(function() {
this.__onIronResizeAsync = null;
this.refit();
}.bind(this));
}
},
@ -583,4 +593,5 @@ context. You should place this element as a child of `<body>` whenever possible.
* @param {{canceled: (boolean|undefined)}} closingReason Contains `canceled` (whether the overlay was canceled).
*/
})();
</script>

View file

@ -38,11 +38,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/
this._backdropElement = null;
// Enable document-wide tap recognizer.
Polymer.Gestures.add(document, 'tap', null);
// We should be using only 'tap', but this would be a breaking change.
var tapEvent = ('ontouchstart' in window) ? 'tap' : 'click';
document.addEventListener(tapEvent, this._onCaptureClick.bind(this), true);
// Listen to mousedown or touchstart to be sure to be the first to capture
// clicks outside the overlay.
var clickEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown';
document.addEventListener(clickEvent, this._onCaptureClick.bind(this), true);
document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
};
@ -167,7 +166,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return;
}
this._overlays.splice(i, 1);
this._setZ(overlay, '');
var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null;
overlay.restoreFocusNode = null;
@ -267,7 +265,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_getZ: function(overlay) {
var z = this._minimumZ;
if (overlay) {
var z1 = Number(window.getComputedStyle(overlay).zIndex);
var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).zIndex);
// Check if is a number
// Number.isNaN not supported in IE 10+
if (z1 === z1) {

View file

@ -127,10 +127,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<input id="focusInput" placeholder="focus input">
<script>
HTMLImports.whenReady(function() {
// Enable document-wide tap recognizer.
Polymer.Gestures.add(document, 'tap', null);
});
function runAfterOpen(overlay, callback) {
overlay.addEventListener('iron-overlay-opened', function() {
Polymer.Base.async(callback, 1);
});
overlay.addEventListener('iron-overlay-opened', callback);
overlay.open();
}
@ -168,10 +172,34 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
overlay.opened = true;
});
test('closed overlay does not refit on iron-resize', function() {
test('open() refits overlay only once', function(done) {
var spy = sinon.spy(overlay, 'refit');
runAfterOpen(overlay, function() {
assert.equal(spy.callCount, 1, 'overlay did refit only once');
done();
});
});
test('open overlay refits on iron-resize', function(done) {
runAfterOpen(overlay, function() {
var spy = sinon.spy(overlay, 'refit');
overlay.fire('iron-resize');
Polymer.dom.flush();
requestAnimationFrame(function() {
assert.isTrue(spy.called, 'overlay did refit');
done();
});
});
});
test('closed overlay does not refit on iron-resize', function(done) {
var spy = sinon.spy(overlay, 'refit');
overlay.fire('iron-resize');
assert.isFalse(spy.called, 'overlay should not refit');
Polymer.dom.flush();
requestAnimationFrame(function() {
assert.isFalse(spy.called, 'overlay should not refit');
done();
});
});
test('open() triggers iron-resize', function(done) {
@ -242,6 +270,21 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
});
test('open overlay on mousedown does not close it', function(done) {
var btn = document.createElement('button');
btn.addEventListener('mousedown', overlay.open.bind(overlay));
document.body.appendChild(btn);
// It triggers mousedown, mouseup, and click.
MockInteractions.tap(btn);
document.body.removeChild(btn);
assert.isTrue(overlay.opened, 'overlay opened');
overlay.async(function() {
assert.isTrue(overlay.opened, 'overlay is still open');
done();
}, 10);
});
test('clicking outside fires iron-overlay-canceled', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
@ -396,18 +439,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
done();
});
});
test('open overlay refits on iron-resize', function(done) {
var spy = sinon.spy(overlay, 'refit');
// At this point, overlay is still opening.
overlay.fire('iron-resize');
assert.isFalse(spy.called, 'overlay did not refit while animating');
overlay.addEventListener('iron-overlay-opened', function() {
overlay.fire('iron-resize');
assert.isTrue(spy.called, 'overlay did refit');
done();
});
});
});
suite('focus handling', function() {
@ -504,17 +535,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
overlay.withBackdrop = true;
var focusableNodes = overlay._focusableNodes;
runAfterOpen(overlay, function() {
// Go to last element.
MockInteractions.focus(focusableNodes[focusableNodes.length-1]);
// Simulate TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[0], document.activeElement, 'focus wrapped to first focusable');
// Simulate Shift+TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9, ['shift']);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[focusableNodes.length-1], document.activeElement, 'focus wrapped to last focusable');
done();
Polymer.Base.async(function() {
// Go to last element.
MockInteractions.focus(focusableNodes[focusableNodes.length-1]);
// Simulate TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[0], document.activeElement, 'focus wrapped to first focusable');
// Simulate Shift+TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9, ['shift']);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[focusableNodes.length-1], document.activeElement, 'focus wrapped to last focusable');
done();
}, 1);
});
});
@ -522,17 +556,19 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
overlayWithTabIndex.withBackdrop = true;
var focusableNodes = overlayWithTabIndex._focusableNodes;
runAfterOpen(overlayWithTabIndex, function() {
// Go to last element.
MockInteractions.focus(focusableNodes[focusableNodes.length-1]);
// Simulate TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[0], document.activeElement, 'focus wrapped to first focusable');
// Simulate Shift+TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9, ['shift']);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[focusableNodes.length-1], document.activeElement, 'focus wrapped to last focusable');
done();
Polymer.Base.async(function() {
// Go to last element.
MockInteractions.focus(focusableNodes[focusableNodes.length-1]);
// Simulate TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[0], document.activeElement, 'focus wrapped to first focusable');
// Simulate Shift+TAB & focus out of overlay.
MockInteractions.pressAndReleaseKeyOn(document, 9, ['shift']);
MockInteractions.focus(document.body);
assert.equal(focusableNodes[focusableNodes.length-1], document.activeElement, 'focus wrapped to last focusable');
done();
}, 1);
});
});
@ -890,7 +926,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
Polymer.Base.async(function() {
assert.lengthOf(document.querySelectorAll('iron-overlay-backdrop'), 0, 'backdrop element removed from the DOM');
done();
}, 1);
}, 100);
});
test('newest overlay appear on top', function(done) {
@ -950,7 +986,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, 1);
});
});
});
suite('always-on-top', function() {
@ -1003,6 +1039,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
suite('animations', function() {
test('overlay animations correctly triggered', function(done) {
var overlay = fixture('basic');
overlay.animated = true;
overlay.open();
overlay.addEventListener('simple-overlay-open-animation-start', function() {
// Since animated overlay will transition center + 300px to center,
// we should not find the element at the center when the open animation starts.
var centerElement = document.elementFromPoint(window.innerWidth/2, window.innerHeight/2);
assert.notEqual(centerElement, overlay, 'overlay should not be centered already');
done();
});
});
});
suite('a11y', function() {
test('overlay has aria-hidden=true when opened', function() {

View file

@ -15,13 +15,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<dom-module id="test-overlay">
<style>
:host {
background: white;
color: black;
border: 1px solid black;
}
:host([animated]) {
-webkit-transition: -webkit-transform 0.3s;
transition: transform 0.3s;
-webkit-transform: translateY(300px);
transform: translateY(300px);
}
:host(.opened[animated]) {
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
</style>
<template>
@ -31,19 +41,62 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</dom-module>
<script>
(function() {
(function() {
Polymer({
Polymer({
is: 'test-overlay',
is: 'test-overlay',
properties: {
animated: {
type: Boolean,
reflectToAttribute: true
}
},
behaviors: [
Polymer.IronOverlayBehavior
]
behaviors: [
Polymer.IronOverlayBehavior
],
});
listeners: {
'transitionend': '__onTransitionEnd'
},
})();
_renderOpened: function() {
if (this.animated) {
if (this.withBackdrop) {
this.backdropElement.open();
}
this.classList.add('opened');
this.fire('simple-overlay-open-animation-start');
} else {
Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments);
}
},
_renderClosed: function() {
if (this.animated) {
if (this.withBackdrop) {
this.backdropElement.close();
}
this.classList.remove('opened');
this.fire('simple-overlay-close-animation-start');
} else {
Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments);
}
},
__onTransitionEnd: function(e) {
if (e && e.target === this) {
if (this.opened) {
this._finishRenderOpened();
} else {
this._finishRenderClosed();
}
}
},
});
})();
</script>