mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
use shared slideshow
This commit is contained in:
parent
c959aa01a2
commit
3eec24c917
86 changed files with 18787 additions and 2233 deletions
44
dashboard-ui/bower_components/emby-webcomponents/slideshow/icons.html
vendored
Normal file
44
dashboard-ui/bower_components/emby-webcomponents/slideshow/icons.html
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<!--
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<!--
|
||||
`iron-icons` is a utility import that includes the definition for the `iron-icon` element, `iron-iconset-svg` element, as well as an import for the default icon set.
|
||||
|
||||
The `iron-icons` directory also includes imports for additional icon sets that can be loaded into your project.
|
||||
|
||||
Example loading icon set:
|
||||
|
||||
<link rel="import" href="../iron-icons/maps-icons.html">
|
||||
|
||||
To use an icon from one of these sets, first prefix your `iron-icon` with the icon set name, followed by a colon, ":", and then the icon id.
|
||||
|
||||
Example using the directions-bus icon from the maps icon set:
|
||||
|
||||
<iron-icon icon="maps:directions-bus"></iron-icon>
|
||||
|
||||
|
||||
See [iron-icon](#iron-icon) for more information about working with icons.
|
||||
|
||||
See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for more information about how to create a custom iconset.
|
||||
|
||||
@group Iron Elements
|
||||
@element iron-icons
|
||||
@demo demo/index.html
|
||||
-->
|
||||
|
||||
<iron-iconset-svg name="slideshow" size="24">
|
||||
<svg>
|
||||
<defs>
|
||||
<g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" /></g>
|
||||
<g id="pause"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" /></g>
|
||||
<g id="skip-next"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" /></g>
|
||||
<g id="skip-previous"><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" /></g>
|
||||
<g id="play-arrow"><path d="M8 5v14l11-7z" /></g>
|
||||
</defs>
|
||||
</svg>
|
||||
</iron-iconset-svg>
|
409
dashboard-ui/bower_components/emby-webcomponents/slideshow/slideshow.js
vendored
Normal file
409
dashboard-ui/bower_components/emby-webcomponents/slideshow/slideshow.js
vendored
Normal file
|
@ -0,0 +1,409 @@
|
|||
define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'css!./style', 'html!./icons', 'iron-icon-set'], function (paperdialoghelper, inputmanager, connectionManager, browser) {
|
||||
|
||||
return function (options) {
|
||||
|
||||
var self = this;
|
||||
var swiperInstance;
|
||||
var dlg;
|
||||
|
||||
function createElements(options) {
|
||||
|
||||
dlg = paperdialoghelper.createDialog({
|
||||
exitAnimationDuration: 800,
|
||||
size: 'fullscreen'
|
||||
});
|
||||
|
||||
dlg.classList.add('slideshowDialog');
|
||||
|
||||
var html = '';
|
||||
|
||||
if (options.interactive) {
|
||||
|
||||
html += '<div>';
|
||||
html += '<div class="slideshowSwiperContainer"><div class="swiper-wrapper"></div></div>';
|
||||
|
||||
html += '<paper-icon-button icon="slideshow:arrow-back" class="btnSlideshowExit" tabindex="-1"></paper-icon-button>';
|
||||
|
||||
html += '<div class="slideshowControlBar">';
|
||||
html += '<paper-icon-button icon="slideshow:skip-previous" class="btnSlideshowPrevious slideshowButton"></paper-icon-button>';
|
||||
html += '<paper-icon-button icon="slideshow:pause" class="btnSlideshowPause slideshowButton" autoFocus></paper-icon-button>';
|
||||
html += '<paper-icon-button icon="slideshow:skip-next" class="btnSlideshowNext slideshowButton"></paper-icon-button>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
} else {
|
||||
html += '<div class="slideshowImage"></div><h1 class="slideshowImageText"></h1>';
|
||||
}
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
if (options.interactive) {
|
||||
dlg.querySelector('.btnSlideshowExit').addEventListener('click', function (e) {
|
||||
|
||||
paperdialoghelper.close(dlg);
|
||||
});
|
||||
dlg.querySelector('.btnSlideshowNext').addEventListener('click', nextImage);
|
||||
dlg.querySelector('.btnSlideshowPrevious').addEventListener('click', previousImage);
|
||||
dlg.querySelector('.btnSlideshowPause').addEventListener('click', playPause);
|
||||
}
|
||||
|
||||
document.body.appendChild(dlg);
|
||||
|
||||
paperdialoghelper.open(dlg).then(function () {
|
||||
|
||||
stopInterval();
|
||||
dlg.parentNode.removeChild(dlg);
|
||||
});
|
||||
|
||||
inputmanager.on(window, onInputCommand);
|
||||
|
||||
dlg.addEventListener('iron-overlay-closed', onDialogClosed);
|
||||
|
||||
if (options.interactive) {
|
||||
loadSwiper(dlg);
|
||||
}
|
||||
}
|
||||
|
||||
function loadSwiper(dlg) {
|
||||
|
||||
if (currentOptions.slides) {
|
||||
dlg.querySelector('.swiper-wrapper').innerHTML = currentOptions.slides.map(getSwiperSlideHtmlFromSlide).join('');
|
||||
} else {
|
||||
dlg.querySelector('.swiper-wrapper').innerHTML = currentOptions.items.map(getSwiperSlideHtmlFromItem).join('');
|
||||
}
|
||||
|
||||
require(['swiper'], function (swiper) {
|
||||
|
||||
swiperInstance = new Swiper(dlg.querySelector('.slideshowSwiperContainer'), {
|
||||
// Optional parameters
|
||||
direction: 'horizontal',
|
||||
loop: true,
|
||||
autoplay: options.interval || 8000,
|
||||
// Disable preloading of all images
|
||||
preloadImages: false,
|
||||
// Enable lazy loading
|
||||
lazyLoading: true,
|
||||
autoplayDisableOnInteraction: false,
|
||||
initialSlide: options.startIndex || 0
|
||||
});
|
||||
|
||||
if (browser.mobile) {
|
||||
pause();
|
||||
} else {
|
||||
play();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSwiperSlideHtmlFromItem(item) {
|
||||
|
||||
return getSwiperSlideHtmlFromSlide({
|
||||
imageUrl: getImgUrl(item)
|
||||
//title: item.Name,
|
||||
//description: item.Overview
|
||||
});
|
||||
}
|
||||
|
||||
function getSwiperSlideHtmlFromSlide(item) {
|
||||
|
||||
var html = '';
|
||||
html += '<div class="swiper-slide">';
|
||||
html += '<img data-src="' + item.imageUrl + '" class="swiper-lazy">';
|
||||
//html += '<paper-spinner class="swiper-lazy-preloader"></paper-spinner>';
|
||||
if (item.title || item.subtitle) {
|
||||
html += '<div class="slideText">';
|
||||
html += '<div class="slideTextInner">';
|
||||
if (item.title) {
|
||||
html += '<div class="slideTitle">';
|
||||
html += item.title;
|
||||
html += '</div>';
|
||||
}
|
||||
if (item.description) {
|
||||
html += '<div class="slideSubtitle">';
|
||||
html += item.description;
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function previousImage() {
|
||||
if (swiperInstance) {
|
||||
swiperInstance.slidePrev();
|
||||
} else {
|
||||
stopInterval();
|
||||
showNextImage(currentIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
function nextImage() {
|
||||
if (swiperInstance) {
|
||||
swiperInstance.slideNext();
|
||||
} else {
|
||||
stopInterval();
|
||||
showNextImage(currentIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
function play() {
|
||||
|
||||
dlg.querySelector('.btnSlideshowPause').icon = "slideshow:pause";
|
||||
swiperInstance.startAutoplay();
|
||||
}
|
||||
|
||||
function pause() {
|
||||
|
||||
dlg.querySelector('.btnSlideshowPause').icon = "slideshow:play-arrow";
|
||||
swiperInstance.stopAutoplay();
|
||||
}
|
||||
|
||||
function playPause() {
|
||||
|
||||
var paused = dlg.querySelector('.btnSlideshowPause').icon != "slideshow:pause";
|
||||
if (paused) {
|
||||
play();
|
||||
} else {
|
||||
pause();
|
||||
}
|
||||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
|
||||
var swiper = swiperInstance;
|
||||
if (swiper) {
|
||||
swiper.destroy(true, true);
|
||||
swiperInstance = null;
|
||||
}
|
||||
|
||||
inputmanager.off(window, onInputCommand);
|
||||
}
|
||||
|
||||
var currentTimeout;
|
||||
var currentIntervalMs;
|
||||
var currentOptions;
|
||||
var currentIndex;
|
||||
|
||||
function startInterval(options) {
|
||||
|
||||
currentOptions = options;
|
||||
|
||||
stopInterval();
|
||||
createElements(options);
|
||||
|
||||
if (!options.interactive) {
|
||||
currentIntervalMs = options.interval || 8000;
|
||||
showNextImage(options.startIndex || 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
function getImgUrl(item) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||
return getBackdropImageUrl(item, {
|
||||
maxWidth: screen.availWidth
|
||||
}, apiClient);
|
||||
} else {
|
||||
return getImageUrl(item, {
|
||||
type: "Primary",
|
||||
maxWidth: screen.availWidth
|
||||
}, apiClient);
|
||||
}
|
||||
}
|
||||
|
||||
function getBackdropImageUrl(item, options, apiClient) {
|
||||
|
||||
options = options || {};
|
||||
options.type = options.type || "Backdrop";
|
||||
|
||||
options.width = null;
|
||||
delete options.width;
|
||||
options.maxWidth = null;
|
||||
delete options.maxWidth;
|
||||
options.maxHeight = null;
|
||||
delete options.maxHeight;
|
||||
options.height = null;
|
||||
delete options.height;
|
||||
|
||||
// If not resizing, get the original image
|
||||
if (!options.maxWidth && !options.width && !options.maxHeight && !options.height) {
|
||||
options.quality = 100;
|
||||
options.format = 'jpg';
|
||||
}
|
||||
|
||||
if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||
|
||||
options.tag = item.BackdropImageTags[0];
|
||||
return apiClient.getScaledImageUrl(item.Id, options);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getImageUrl(item, options, apiClient) {
|
||||
|
||||
options = options || {};
|
||||
options.type = options.type || "Primary";
|
||||
|
||||
if (typeof (item) === 'string') {
|
||||
return apiClient.getScaledImageUrl(item, options);
|
||||
}
|
||||
|
||||
if (item.ImageTags && item.ImageTags[options.type]) {
|
||||
|
||||
options.tag = item.ImageTags[options.type];
|
||||
return apiClient.getScaledImageUrl(item.Id, options);
|
||||
}
|
||||
|
||||
if (options.type == 'Primary') {
|
||||
if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
||||
|
||||
options.tag = item.AlbumPrimaryImageTag;
|
||||
return apiClient.getScaledImageUrl(item.AlbumId, options);
|
||||
}
|
||||
|
||||
//else if (item.AlbumId && item.SeriesPrimaryImageTag) {
|
||||
|
||||
// imgUrl = ApiClient.getScaledImageUrl(item.SeriesId, {
|
||||
// type: "Primary",
|
||||
// width: downloadWidth,
|
||||
// tag: item.SeriesPrimaryImageTag,
|
||||
// minScale: minScale
|
||||
// });
|
||||
|
||||
//}
|
||||
//else if (item.ParentPrimaryImageTag) {
|
||||
|
||||
// imgUrl = ApiClient.getImageUrl(item.ParentPrimaryImageItemId, {
|
||||
// type: "Primary",
|
||||
// width: downloadWidth,
|
||||
// tag: item.ParentPrimaryImageTag,
|
||||
// minScale: minScale
|
||||
// });
|
||||
//}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function showNextImage(index, skipPreload) {
|
||||
|
||||
index = Math.max(0, index);
|
||||
if (index >= currentOptions.items.length) {
|
||||
index = 0;
|
||||
}
|
||||
currentIndex = index;
|
||||
|
||||
var options = currentOptions;
|
||||
var items = options.items;
|
||||
var item = items[index];
|
||||
var imgUrl = getImgUrl(item);
|
||||
|
||||
var onSrcLoaded = function () {
|
||||
var cardImageContainer = dlg.querySelector('.slideshowImage');
|
||||
|
||||
var newCardImageContainer = document.createElement('div');
|
||||
newCardImageContainer.className = cardImageContainer.className;
|
||||
|
||||
if (options.cover) {
|
||||
newCardImageContainer.classList.add('cover');
|
||||
}
|
||||
|
||||
newCardImageContainer.style.backgroundImage = "url('" + imgUrl + "')";
|
||||
newCardImageContainer.classList.add('hide');
|
||||
cardImageContainer.parentNode.appendChild(newCardImageContainer);
|
||||
|
||||
if (options.showTitle) {
|
||||
dlg.querySelector('.slideshowImageText').innerHTML = item.Name;
|
||||
} else {
|
||||
dlg.querySelector('.slideshowImageText').innerHTML = '';
|
||||
}
|
||||
|
||||
newCardImageContainer.classList.remove('hide');
|
||||
var onAnimationFinished = function () {
|
||||
|
||||
var parentNode = cardImageContainer.parentNode;
|
||||
if (parentNode) {
|
||||
parentNode.removeChild(cardImageContainer);
|
||||
}
|
||||
};
|
||||
|
||||
if (newCardImageContainer.animate) {
|
||||
|
||||
var keyframes = [
|
||||
{ opacity: '0', offset: 0 },
|
||||
{ opacity: '1', offset: 1 }];
|
||||
var timing = { duration: 1200, iterations: 1 };
|
||||
newCardImageContainer.animate(keyframes, timing).onfinish = onAnimationFinished;
|
||||
} else {
|
||||
onAnimationFinished();
|
||||
}
|
||||
|
||||
stopInterval();
|
||||
currentTimeout = setTimeout(function () {
|
||||
showNextImage(index + 1, true);
|
||||
|
||||
}, currentIntervalMs);
|
||||
};
|
||||
|
||||
if (!skipPreload) {
|
||||
var img = new Image();
|
||||
img.onload = onSrcLoaded;
|
||||
img.src = imgUrl;
|
||||
} else {
|
||||
onSrcLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
function stopInterval() {
|
||||
if (currentTimeout) {
|
||||
clearTimeout(currentTimeout);
|
||||
currentTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
|
||||
switch (e.detail.command) {
|
||||
|
||||
case 'left':
|
||||
previousImage();
|
||||
break;
|
||||
case 'right':
|
||||
nextImage();
|
||||
break;
|
||||
case 'play':
|
||||
play();
|
||||
break;
|
||||
case 'pause':
|
||||
pause();
|
||||
break;
|
||||
case 'playpause':
|
||||
playPause();
|
||||
break;
|
||||
default:
|
||||
return
|
||||
break;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
self.show = function () {
|
||||
startInterval(options);
|
||||
};
|
||||
|
||||
self.hide = function () {
|
||||
|
||||
var dialog = dlg;
|
||||
if (dialog) {
|
||||
|
||||
paperdialoghelper.close(dialog);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
104
dashboard-ui/bower_components/emby-webcomponents/slideshow/style.css
vendored
Normal file
104
dashboard-ui/bower_components/emby-webcomponents/slideshow/style.css
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
.slideshowImage, .slideshowSwiperContainer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1001;
|
||||
background-position: center center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.slideshowImage.cover {
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.slideshowImageText {
|
||||
position: fixed;
|
||||
bottom: .25em;
|
||||
right: .5em;
|
||||
color: #fff;
|
||||
z-index: 1002;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.swiper-slide {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.swiper-slide img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
-moz-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.btnSlideshowExit {
|
||||
z-index: 1002;
|
||||
position: absolute;
|
||||
top: 1%;
|
||||
left: .5%;
|
||||
width: 6vh;
|
||||
height: 6vh;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.slideshowControlBar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1002;
|
||||
background: rgba(0,0,0,.5);
|
||||
text-align: center;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.mouseIdle .btnSlideshowExit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mouseIdle .slideshowControlBar {
|
||||
transform: translateY(100%);
|
||||
transition: transform 600ms ease-out;
|
||||
}
|
||||
|
||||
.slideshowButton {
|
||||
width: 8vh;
|
||||
height: 8vh;
|
||||
}
|
||||
|
||||
.slideText {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 10vh;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.slideTextInner {
|
||||
margin: 0 auto;
|
||||
max-width: 60%;
|
||||
background: rgba(0,0,0,.8);
|
||||
display: inline-block;
|
||||
padding: .5em 1em;
|
||||
border-radius: .25em;
|
||||
}
|
||||
|
||||
.slideTitle {
|
||||
font-size: 180%;
|
||||
}
|
||||
|
||||
.slideSubtitle {
|
||||
color: #ccc;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue