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

247 lines
7.6 KiB
JavaScript
Raw Normal View History

2020-08-01 19:18:03 +02:00
import 'css!components/viewManager/viewContainer';
2020-08-01 05:36:36 +02:00
/* eslint-disable indent */
2018-10-23 01:05:09 +03:00
function setControllerClass(view, options) {
2019-04-02 22:10:22 +01:00
if (options.controllerFactory) {
return Promise.resolve();
}
2020-08-01 05:36:36 +02:00
let controllerUrl = view.getAttribute('data-controller');
2019-04-02 22:10:22 +01:00
if (controllerUrl) {
2020-07-30 16:07:13 +02:00
if (controllerUrl.indexOf('__plugin/') === 0) {
2020-05-04 12:44:12 +02:00
controllerUrl = controllerUrl.substring('__plugin/'.length);
2019-04-02 22:10:22 +01:00
}
controllerUrl = Dashboard.getConfigurationResourceUrl(controllerUrl);
2020-08-01 19:18:03 +02:00
return import(controllerUrl).then((ControllerFactory) => {
2019-04-02 22:10:22 +01:00
options.controllerFactory = ControllerFactory;
});
}
return Promise.resolve();
2018-10-23 01:05:09 +03:00
}
2020-08-01 05:36:36 +02:00
export function loadView(options) {
2018-10-23 01:05:09 +03:00
if (!options.cancel) {
2020-08-01 05:36:36 +02:00
const selected = selectedPageIndex;
const previousAnimatable = selected === -1 ? null : allPages[selected];
let pageIndex = selected + 1;
2019-04-02 22:10:22 +01:00
if (pageIndex >= pageContainerCount) {
pageIndex = 0;
}
2020-08-01 05:36:36 +02:00
const isPluginpage = options.url.toLowerCase().indexOf('/configurationpage') !== -1;
const newViewInfo = normalizeNewView(options, isPluginpage);
const newView = newViewInfo.elem;
2020-08-01 05:36:36 +02:00
return new Promise((resolve) => {
2020-08-01 19:18:03 +02:00
const currentPage = allPages[pageIndex];
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (currentPage) {
triggerDestroy(currentPage);
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
let view = newView;
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (typeof view == 'string') {
view = document.createElement('div');
view.innerHTML = newView;
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
view.classList.add('mainAnimatedPage');
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (currentPage) {
if (newViewInfo.hasScript && window.$) {
mainAnimatedPages.removeChild(currentPage);
view = $(view).appendTo(mainAnimatedPages)[0];
} else {
2020-08-01 19:18:03 +02:00
mainAnimatedPages.replaceChild(view, currentPage);
2019-04-02 22:10:22 +01:00
}
2020-08-01 19:18:03 +02:00
} else {
if (newViewInfo.hasScript && window.$) {
view = $(view).appendTo(mainAnimatedPages)[0];
} else {
mainAnimatedPages.appendChild(view);
2020-01-04 01:31:35 +01:00
}
2020-08-01 19:18:03 +02:00
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (options.type) {
view.setAttribute('data-type', options.type);
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
const properties = [];
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (options.fullscreen) {
properties.push('fullscreen');
}
if (properties.length) {
view.setAttribute('data-properties', properties.join(','));
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
allPages[pageIndex] = view;
setControllerClass(view, options).then(() => {
if (onBeforeChange) {
onBeforeChange(view, false, options);
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
beforeAnimate(allPages, pageIndex, selected);
selectedPageIndex = pageIndex;
currentUrls[pageIndex] = options.url;
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
if (!options.cancel && previousAnimatable) {
afterAnimate(allPages, pageIndex);
}
2020-01-04 01:31:35 +01:00
2020-08-01 19:18:03 +02:00
if (window.$) {
$.mobile = $.mobile || {};
$.mobile.activePage = view;
}
2019-04-02 22:10:22 +01:00
2020-08-01 19:18:03 +02:00
resolve(view);
2019-04-02 22:10:22 +01:00
});
});
2018-10-23 01:05:09 +03:00
}
}
function replaceAll(str, find, replace) {
2019-04-02 22:10:22 +01:00
return str.split(find).join(replace);
2018-10-23 01:05:09 +03:00
}
function parseHtml(html, hasScript) {
2019-04-02 22:10:22 +01:00
if (hasScript) {
2020-05-04 12:44:12 +02:00
html = replaceAll(html, '\x3c!--<script', '<script');
html = replaceAll(html, '<\/script>--\x3e', '<\/script>');
2019-04-02 22:10:22 +01:00
}
2020-08-01 05:36:36 +02:00
const wrapper = document.createElement('div');
2019-04-02 22:10:22 +01:00
wrapper.innerHTML = html;
return wrapper.querySelector('div[data-role="page"]');
2018-10-23 01:05:09 +03:00
}
function normalizeNewView(options, isPluginpage) {
2020-08-01 05:36:36 +02:00
const viewHtml = options.view;
2019-04-02 22:10:22 +01:00
2020-07-30 16:07:13 +02:00
if (viewHtml.indexOf('data-role="page"') === -1) {
2019-04-02 22:10:22 +01:00
return viewHtml;
}
2020-08-01 05:36:36 +02:00
let hasScript = viewHtml.indexOf('<script') !== -1;
const elem = parseHtml(viewHtml, hasScript);
2019-04-02 22:10:22 +01:00
if (hasScript) {
2020-07-30 16:07:13 +02:00
hasScript = elem.querySelector('script') != null;
2019-04-02 22:10:22 +01:00
}
2020-08-01 05:36:36 +02:00
let hasjQuery = false;
let hasjQuerySelect = false;
let hasjQueryChecked = false;
2019-04-02 22:10:22 +01:00
if (isPluginpage) {
2020-07-30 16:07:13 +02:00
hasjQuery = viewHtml.indexOf('jQuery') != -1 || viewHtml.indexOf('$(') != -1 || viewHtml.indexOf('$.') != -1;
hasjQueryChecked = viewHtml.indexOf('.checked(') != -1;
hasjQuerySelect = viewHtml.indexOf('.selectmenu(') != -1;
2019-04-02 22:10:22 +01:00
}
return {
2018-10-23 01:05:09 +03:00
elem: elem,
hasScript: hasScript,
hasjQuerySelect: hasjQuerySelect,
hasjQueryChecked: hasjQueryChecked,
hasjQuery: hasjQuery
2019-04-02 22:10:22 +01:00
};
2018-10-23 01:05:09 +03:00
}
function beforeAnimate(allPages, newPageIndex, oldPageIndex) {
2020-08-01 05:36:36 +02:00
for (let index = 0, length = allPages.length; index < length; index++) {
if (newPageIndex !== index && oldPageIndex !== index) {
2020-05-04 12:44:12 +02:00
allPages[index].classList.add('hide');
2019-04-02 22:10:22 +01:00
}
}
2018-10-23 01:05:09 +03:00
}
function afterAnimate(allPages, newPageIndex) {
2020-08-01 05:36:36 +02:00
for (let index = 0, length = allPages.length; index < length; index++) {
if (newPageIndex !== index) {
2020-05-04 12:44:12 +02:00
allPages[index].classList.add('hide');
2019-04-02 22:10:22 +01:00
}
}
2018-10-23 01:05:09 +03:00
}
2020-08-01 05:36:36 +02:00
export function setOnBeforeChange(fn) {
2019-04-02 22:10:22 +01:00
onBeforeChange = fn;
2018-10-23 01:05:09 +03:00
}
2020-08-01 05:36:36 +02:00
export function tryRestoreView(options) {
const url = options.url;
const index = currentUrls.indexOf(url);
2019-04-02 22:10:22 +01:00
2020-07-30 16:07:13 +02:00
if (index !== -1) {
2020-08-01 05:36:36 +02:00
const animatable = allPages[index];
const view = animatable;
2019-04-02 22:10:22 +01:00
2018-10-23 01:05:09 +03:00
if (view) {
2019-04-02 22:10:22 +01:00
if (options.cancel) {
return;
}
2020-08-01 05:36:36 +02:00
const selected = selectedPageIndex;
const previousAnimatable = selected === -1 ? null : allPages[selected];
return setControllerClass(view, options).then(() => {
2019-04-02 22:10:22 +01:00
if (onBeforeChange) {
onBeforeChange(view, true, options);
}
beforeAnimate(allPages, index, selected);
2020-05-04 12:44:12 +02:00
animatable.classList.remove('hide');
2019-04-02 22:10:22 +01:00
selectedPageIndex = index;
if (!options.cancel && previousAnimatable) {
afterAnimate(allPages, index);
}
if (window.$) {
$.mobile = $.mobile || {};
$.mobile.activePage = view;
}
return view;
});
2018-10-23 01:05:09 +03:00
}
}
2019-04-02 22:10:22 +01:00
return Promise.reject();
2018-10-23 01:05:09 +03:00
}
function triggerDestroy(view) {
2020-05-04 12:44:12 +02:00
view.dispatchEvent(new CustomEvent('viewdestroy', {}));
2018-10-23 01:05:09 +03:00
}
2020-08-01 05:36:36 +02:00
export function reset() {
2019-04-02 22:10:22 +01:00
allPages = [];
currentUrls = [];
2020-05-04 12:44:12 +02:00
mainAnimatedPages.innerHTML = '';
2018-10-23 01:05:09 +03:00
selectedPageIndex = -1;
2019-04-02 22:10:22 +01:00
}
2020-08-01 05:36:36 +02:00
let onBeforeChange;
const mainAnimatedPages = document.querySelector('.mainAnimatedPages');
let allPages = [];
let currentUrls = [];
const pageContainerCount = 3;
let selectedPageIndex = -1;
2019-04-02 22:10:22 +01:00
reset();
2020-05-04 12:44:12 +02:00
mainAnimatedPages.classList.remove('hide');
2020-08-01 05:36:36 +02:00
/* eslint-enable indent */
export default {
loadView: loadView,
tryRestoreView: tryRestoreView,
reset: reset,
setOnBeforeChange: setOnBeforeChange
};