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

Fix indentation issues

This commit is contained in:
Bill Thornton 2023-04-19 01:56:05 -04:00
parent 52c8cffc82
commit f2726653ae
120 changed files with 30271 additions and 30631 deletions

View file

@ -3,109 +3,106 @@ import dom from '../../scripts/dom';
import './emby-checkbox.scss';
import 'webcomponents.js/webcomponents-lite';
/* eslint-disable indent */
const EmbyCheckboxPrototype = Object.create(HTMLInputElement.prototype);
const EmbyCheckboxPrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) {
// Don't submit form on enter
// Real (non-emulator) Tizen does nothing on Space
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
e.preventDefault();
function onKeyDown(e) {
// Don't submit form on enter
// Real (non-emulator) Tizen does nothing on Space
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
e.preventDefault();
this.checked = !this.checked;
this.checked = !this.checked;
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
return false;
}
}
return false;
}
const enableRefreshHack = browser.tizen || browser.orsay || browser.operaTv || browser.web0s ? true : false;
function forceRefresh(loading) {
const elem = this.parentNode;
elem.style.webkitAnimationName = 'repaintChrome';
elem.style.webkitAnimationDelay = (loading === true ? '500ms' : '');
elem.style.webkitAnimationDuration = '10ms';
elem.style.webkitAnimationIterationCount = '1';
setTimeout(function () {
elem.style.webkitAnimationName = '';
}, (loading === true ? 520 : 20));
}
EmbyCheckboxPrototype.attachedCallback = function () {
if (this.getAttribute('data-embycheckbox') === 'true') {
return;
}
const enableRefreshHack = browser.tizen || browser.orsay || browser.operaTv || browser.web0s ? true : false;
this.setAttribute('data-embycheckbox', 'true');
function forceRefresh(loading) {
const elem = this.parentNode;
this.classList.add('emby-checkbox');
elem.style.webkitAnimationName = 'repaintChrome';
elem.style.webkitAnimationDelay = (loading === true ? '500ms' : '');
elem.style.webkitAnimationDuration = '10ms';
elem.style.webkitAnimationIterationCount = '1';
const labelElement = this.parentNode;
labelElement.classList.add('emby-checkbox-label');
setTimeout(function () {
elem.style.webkitAnimationName = '';
}, (loading === true ? 520 : 20));
const labelTextElement = labelElement.querySelector('span');
let outlineClass = 'checkboxOutline';
const customClass = this.getAttribute('data-outlineclass');
if (customClass) {
outlineClass += ' ' + customClass;
}
EmbyCheckboxPrototype.attachedCallback = function () {
if (this.getAttribute('data-embycheckbox') === 'true') {
return;
}
const checkedIcon = this.getAttribute('data-checkedicon') || 'check';
const uncheckedIcon = this.getAttribute('data-uncheckedicon') || '';
const checkHtml = '<span class="material-icons checkboxIcon checkboxIcon-checked ' + checkedIcon + '" aria-hidden="true"></span>';
const uncheckedHtml = '<span class="material-icons checkboxIcon checkboxIcon-unchecked ' + uncheckedIcon + '" aria-hidden="true"></span>';
labelElement.insertAdjacentHTML('beforeend', '<span class="' + outlineClass + '">' + checkHtml + uncheckedHtml + '</span>');
this.setAttribute('data-embycheckbox', 'true');
labelTextElement.classList.add('checkboxLabel');
this.classList.add('emby-checkbox');
this.addEventListener('keydown', onKeyDown);
const labelElement = this.parentNode;
labelElement.classList.add('emby-checkbox-label');
const labelTextElement = labelElement.querySelector('span');
let outlineClass = 'checkboxOutline';
const customClass = this.getAttribute('data-outlineclass');
if (customClass) {
outlineClass += ' ' + customClass;
}
const checkedIcon = this.getAttribute('data-checkedicon') || 'check';
const uncheckedIcon = this.getAttribute('data-uncheckedicon') || '';
const checkHtml = '<span class="material-icons checkboxIcon checkboxIcon-checked ' + checkedIcon + '" aria-hidden="true"></span>';
const uncheckedHtml = '<span class="material-icons checkboxIcon checkboxIcon-unchecked ' + uncheckedIcon + '" aria-hidden="true"></span>';
labelElement.insertAdjacentHTML('beforeend', '<span class="' + outlineClass + '">' + checkHtml + uncheckedHtml + '</span>');
labelTextElement.classList.add('checkboxLabel');
this.addEventListener('keydown', onKeyDown);
if (enableRefreshHack) {
forceRefresh.call(this, true);
dom.addEventListener(this, 'click', forceRefresh, {
passive: true
});
dom.addEventListener(this, 'blur', forceRefresh, {
passive: true
});
dom.addEventListener(this, 'focus', forceRefresh, {
passive: true
});
dom.addEventListener(this, 'change', forceRefresh, {
passive: true
});
}
};
EmbyCheckboxPrototype.detachedCallback = function () {
this.removeEventListener('keydown', onKeyDown);
dom.removeEventListener(this, 'click', forceRefresh, {
if (enableRefreshHack) {
forceRefresh.call(this, true);
dom.addEventListener(this, 'click', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'blur', forceRefresh, {
dom.addEventListener(this, 'blur', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'focus', forceRefresh, {
dom.addEventListener(this, 'focus', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'change', forceRefresh, {
dom.addEventListener(this, 'change', forceRefresh, {
passive: true
});
};
}
};
document.registerElement('emby-checkbox', {
prototype: EmbyCheckboxPrototype,
extends: 'input'
EmbyCheckboxPrototype.detachedCallback = function () {
this.removeEventListener('keydown', onKeyDown);
dom.removeEventListener(this, 'click', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'blur', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'focus', forceRefresh, {
passive: true
});
dom.removeEventListener(this, 'change', forceRefresh, {
passive: true
});
};
document.registerElement('emby-checkbox', {
prototype: EmbyCheckboxPrototype,
extends: 'input'
});
/* eslint-enable indent */

View file

@ -2,101 +2,98 @@ import './emby-collapse.scss';
import 'webcomponents.js/webcomponents-lite';
import '../emby-button/emby-button';
/* eslint-disable indent */
const EmbyButtonPrototype = Object.create(HTMLDivElement.prototype);
const EmbyButtonPrototype = Object.create(HTMLDivElement.prototype);
function slideDownToShow(button, elem) {
requestAnimationFrame(() => {
elem.classList.remove('hide');
elem.classList.add('expanded');
elem.style.height = 'auto';
const height = elem.offsetHeight + 'px';
elem.style.height = '0';
// trigger reflow
// TODO: Find a better way to do this
const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */
elem.style.height = height;
function slideDownToShow(button, elem) {
requestAnimationFrame(() => {
elem.classList.remove('hide');
elem.classList.add('expanded');
setTimeout(function () {
if (elem.classList.contains('expanded')) {
elem.classList.remove('hide');
} else {
elem.classList.add('hide');
}
elem.style.height = 'auto';
const height = elem.offsetHeight + 'px';
elem.style.height = '0';
// trigger reflow
// TODO: Find a better way to do this
const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */
elem.style.height = height;
}, 300);
setTimeout(function () {
if (elem.classList.contains('expanded')) {
elem.classList.remove('hide');
} else {
elem.classList.add('hide');
}
elem.style.height = 'auto';
}, 300);
const icon = button.querySelector('.material-icons');
icon.classList.add('emby-collapse-expandIconExpanded');
});
}
function slideUpToHide(button, elem) {
requestAnimationFrame(() => {
elem.style.height = elem.offsetHeight + 'px';
// trigger reflow
// TODO: Find a better way to do this
const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */
elem.classList.remove('expanded');
elem.style.height = '0';
setTimeout(function () {
if (elem.classList.contains('expanded')) {
elem.classList.remove('hide');
} else {
elem.classList.add('hide');
}
}, 300);
const icon = button.querySelector('.material-icons');
icon.classList.remove('emby-collapse-expandIconExpanded');
});
}
function onButtonClick() {
const button = this;
const collapseContent = button.parentNode.querySelector('.collapseContent');
if (collapseContent.expanded) {
collapseContent.expanded = false;
slideUpToHide(button, collapseContent);
} else {
collapseContent.expanded = true;
slideDownToShow(button, collapseContent);
}
}
EmbyButtonPrototype.attachedCallback = function () {
if (this.classList.contains('emby-collapse')) {
return;
}
this.classList.add('emby-collapse');
const collapseContent = this.querySelector('.collapseContent');
if (collapseContent) {
collapseContent.classList.add('hide');
}
const title = this.getAttribute('title');
const html = '<button is="emby-button" type="button" on-click="toggleExpand" id="expandButton" class="emby-collapsible-button iconRight"><h3 class="emby-collapsible-title" title="' + title + '">' + title + '</h3><span class="material-icons emby-collapse-expandIcon expand_more" aria-hidden="true"></span></button>';
this.insertAdjacentHTML('afterbegin', html);
const button = this.querySelector('.emby-collapsible-button');
button.addEventListener('click', onButtonClick);
if (this.getAttribute('data-expanded') === 'true') {
onButtonClick.call(button);
}
};
document.registerElement('emby-collapse', {
prototype: EmbyButtonPrototype,
extends: 'div'
const icon = button.querySelector('.material-icons');
icon.classList.add('emby-collapse-expandIconExpanded');
});
}
function slideUpToHide(button, elem) {
requestAnimationFrame(() => {
elem.style.height = elem.offsetHeight + 'px';
// trigger reflow
// TODO: Find a better way to do this
const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */
elem.classList.remove('expanded');
elem.style.height = '0';
setTimeout(function () {
if (elem.classList.contains('expanded')) {
elem.classList.remove('hide');
} else {
elem.classList.add('hide');
}
}, 300);
const icon = button.querySelector('.material-icons');
icon.classList.remove('emby-collapse-expandIconExpanded');
});
}
function onButtonClick() {
const button = this;
const collapseContent = button.parentNode.querySelector('.collapseContent');
if (collapseContent.expanded) {
collapseContent.expanded = false;
slideUpToHide(button, collapseContent);
} else {
collapseContent.expanded = true;
slideDownToShow(button, collapseContent);
}
}
EmbyButtonPrototype.attachedCallback = function () {
if (this.classList.contains('emby-collapse')) {
return;
}
this.classList.add('emby-collapse');
const collapseContent = this.querySelector('.collapseContent');
if (collapseContent) {
collapseContent.classList.add('hide');
}
const title = this.getAttribute('title');
const html = '<button is="emby-button" type="button" on-click="toggleExpand" id="expandButton" class="emby-collapsible-button iconRight"><h3 class="emby-collapsible-title" title="' + title + '">' + title + '</h3><span class="material-icons emby-collapse-expandIcon expand_more" aria-hidden="true"></span></button>';
this.insertAdjacentHTML('afterbegin', html);
const button = this.querySelector('.emby-collapsible-button');
button.addEventListener('click', onButtonClick);
if (this.getAttribute('data-expanded') === 'true') {
onButtonClick.call(button);
}
};
document.registerElement('emby-collapse', {
prototype: EmbyButtonPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -3,119 +3,116 @@ import dom from '../../scripts/dom';
import './emby-input.scss';
import 'webcomponents.js/webcomponents-lite';
/* eslint-disable indent */
const EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
const EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
let inputId = 0;
let supportsFloatingLabel = false;
let inputId = 0;
let supportsFloatingLabel = false;
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
// descriptor returning null in webos
if (descriptor && descriptor.configurable) {
const baseSetMethod = descriptor.set;
descriptor.set = function (value) {
baseSetMethod.call(this, value);
// descriptor returning null in webos
if (descriptor && descriptor.configurable) {
const baseSetMethod = descriptor.set;
descriptor.set = function (value) {
baseSetMethod.call(this, value);
this.dispatchEvent(new CustomEvent('valueset', {
bubbles: false,
cancelable: false
}));
};
this.dispatchEvent(new CustomEvent('valueset', {
bubbles: false,
cancelable: false
}));
};
Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor);
supportsFloatingLabel = true;
}
}
Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor);
supportsFloatingLabel = true;
}
EmbyInputPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embyinput' + inputId;
inputId++;
}
EmbyInputPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embyinput' + inputId;
inputId++;
}
if (this.classList.contains('emby-input')) {
return;
}
if (this.classList.contains('emby-input')) {
return;
}
this.classList.add('emby-input');
this.classList.add('emby-input');
const parentNode = this.parentNode;
const document = this.ownerDocument;
const label = document.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('inputLabel');
label.classList.add('inputLabelUnfocused');
const parentNode = this.parentNode;
const document = this.ownerDocument;
const label = document.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('inputLabel');
label.classList.add('inputLabelUnfocused');
label.htmlFor = this.id;
parentNode.insertBefore(label, this);
this.labelElement = label;
label.htmlFor = this.id;
parentNode.insertBefore(label, this);
this.labelElement = label;
dom.addEventListener(this, 'focus', function () {
onChange.call(this);
dom.addEventListener(this, 'focus', function () {
onChange.call(this);
// For Samsung orsay devices
if (document.attachIME) {
document.attachIME(this);
}
label.classList.add('inputLabelFocused');
label.classList.remove('inputLabelUnfocused');
}, {
passive: true
});
dom.addEventListener(this, 'blur', function () {
onChange.call(this);
label.classList.remove('inputLabelFocused');
label.classList.add('inputLabelUnfocused');
}, {
passive: true
});
dom.addEventListener(this, 'change', onChange, {
passive: true
});
dom.addEventListener(this, 'input', onChange, {
passive: true
});
dom.addEventListener(this, 'valueset', onChange, {
passive: true
});
//Make sure the IME pops up if this is the first/default element on the page
if (browser.orsay && this === document.activeElement && document.attachIME) {
// For Samsung orsay devices
if (document.attachIME) {
document.attachIME(this);
}
};
function onChange() {
const label = this.labelElement;
if (this.value) {
label.classList.remove('inputLabel-float');
} else {
const instanceSupportsFloat = supportsFloatingLabel && this.type !== 'date' && this.type !== 'time';
if (instanceSupportsFloat) {
label.classList.add('inputLabel-float');
}
}
}
EmbyInputPrototype.attachedCallback = function () {
this.labelElement.htmlFor = this.id;
onChange.call(this);
};
EmbyInputPrototype.label = function (text) {
this.labelElement.innerText = text;
};
document.registerElement('emby-input', {
prototype: EmbyInputPrototype,
extends: 'input'
label.classList.add('inputLabelFocused');
label.classList.remove('inputLabelUnfocused');
}, {
passive: true
});
/* eslint-enable indent */
dom.addEventListener(this, 'blur', function () {
onChange.call(this);
label.classList.remove('inputLabelFocused');
label.classList.add('inputLabelUnfocused');
}, {
passive: true
});
dom.addEventListener(this, 'change', onChange, {
passive: true
});
dom.addEventListener(this, 'input', onChange, {
passive: true
});
dom.addEventListener(this, 'valueset', onChange, {
passive: true
});
//Make sure the IME pops up if this is the first/default element on the page
if (browser.orsay && this === document.activeElement && document.attachIME) {
document.attachIME(this);
}
};
function onChange() {
const label = this.labelElement;
if (this.value) {
label.classList.remove('inputLabel-float');
} else {
const instanceSupportsFloat = supportsFloatingLabel && this.type !== 'date' && this.type !== 'time';
if (instanceSupportsFloat) {
label.classList.add('inputLabel-float');
}
}
}
EmbyInputPrototype.attachedCallback = function () {
this.labelElement.htmlFor = this.id;
onChange.call(this);
};
EmbyInputPrototype.label = function (text) {
this.labelElement.innerText = text;
};
document.registerElement('emby-input', {
prototype: EmbyInputPrototype,
extends: 'input'
});

View file

@ -5,73 +5,70 @@ import Events from '../../utils/events.ts';
import 'webcomponents.js/webcomponents-lite';
/* eslint-disable indent */
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
}
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
}
}
function onRefreshProgress(e, apiClient, info) {
const indicator = this;
if (!indicator.itemId) {
indicator.itemId = dom.parentWithAttribute(indicator, 'data-id').getAttribute('data-id');
}
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
if (info.ItemId === indicator.itemId) {
const progress = parseFloat(info.Progress);
if (progress && progress < 100) {
this.classList.remove('hide');
} else {
this.classList.add('hide');
}
this.setAttribute('data-progress', progress);
}
}
const EmbyItemRefreshIndicatorPrototype = Object.create(EmbyProgressRing);
EmbyItemRefreshIndicatorPrototype.createdCallback = function () {
// base method
if (EmbyProgressRing.createdCallback) {
EmbyProgressRing.createdCallback.call(this);
}
function onRefreshProgress(e, apiClient, info) {
const indicator = this;
addNotificationEvent(this, 'RefreshProgress', onRefreshProgress);
};
if (!indicator.itemId) {
indicator.itemId = dom.parentWithAttribute(indicator, 'data-id').getAttribute('data-id');
}
EmbyItemRefreshIndicatorPrototype.attachedCallback = function () {
// base method
if (EmbyProgressRing.attachedCallback) {
EmbyProgressRing.attachedCallback.call(this);
}
};
if (info.ItemId === indicator.itemId) {
const progress = parseFloat(info.Progress);
if (progress && progress < 100) {
this.classList.remove('hide');
} else {
this.classList.add('hide');
}
this.setAttribute('data-progress', progress);
}
EmbyItemRefreshIndicatorPrototype.detachedCallback = function () {
// base method
if (EmbyProgressRing.detachedCallback) {
EmbyProgressRing.detachedCallback.call(this);
}
const EmbyItemRefreshIndicatorPrototype = Object.create(EmbyProgressRing);
removeNotificationEvent(this, 'RefreshProgress');
this.itemId = null;
};
EmbyItemRefreshIndicatorPrototype.createdCallback = function () {
// base method
if (EmbyProgressRing.createdCallback) {
EmbyProgressRing.createdCallback.call(this);
}
document.registerElement('emby-itemrefreshindicator', {
prototype: EmbyItemRefreshIndicatorPrototype,
extends: 'div'
});
addNotificationEvent(this, 'RefreshProgress', onRefreshProgress);
};
EmbyItemRefreshIndicatorPrototype.attachedCallback = function () {
// base method
if (EmbyProgressRing.attachedCallback) {
EmbyProgressRing.attachedCallback.call(this);
}
};
EmbyItemRefreshIndicatorPrototype.detachedCallback = function () {
// base method
if (EmbyProgressRing.detachedCallback) {
EmbyProgressRing.detachedCallback.call(this);
}
removeNotificationEvent(this, 'RefreshProgress');
this.itemId = null;
};
document.registerElement('emby-itemrefreshindicator', {
prototype: EmbyItemRefreshIndicatorPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -13,471 +13,468 @@ import 'webcomponents.js/webcomponents-lite';
import ServerConnections from '../../components/ServerConnections';
import Sortable from 'sortablejs';
/* eslint-disable indent */
const ItemsContainerPrototype = Object.create(HTMLDivElement.prototype);
const ItemsContainerPrototype = Object.create(HTMLDivElement.prototype);
function onClick(e) {
const itemsContainer = this;
const multiSelect = itemsContainer.multiSelect;
function onClick(e) {
const itemsContainer = this;
const multiSelect = itemsContainer.multiSelect;
if (multiSelect?.onContainerClick.call(itemsContainer, e) === false) {
return;
}
itemShortcuts.onClick.call(itemsContainer, e);
if (multiSelect?.onContainerClick.call(itemsContainer, e) === false) {
return;
}
function disableEvent(e) {
itemShortcuts.onClick.call(itemsContainer, e);
}
function disableEvent(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
function onContextMenu(e) {
const target = e.target;
const card = dom.parentWithAttribute(target, 'data-id');
// check for serverId, it won't be present on selectserver
if (card && card.getAttribute('data-serverid')) {
inputManager.handleCommand('menu', {
sourceElement: card
});
e.preventDefault();
e.stopPropagation();
return false;
}
}
function onContextMenu(e) {
const target = e.target;
const card = dom.parentWithAttribute(target, 'data-id');
// check for serverId, it won't be present on selectserver
if (card && card.getAttribute('data-serverid')) {
inputManager.handleCommand('menu', {
sourceElement: card
});
e.preventDefault();
e.stopPropagation();
return false;
}
}
function getShortcutOptions() {
return {
click: false
};
}
ItemsContainerPrototype.enableMultiSelect = function (enabled) {
const current = this.multiSelect;
if (!enabled) {
if (current) {
current.destroy();
this.multiSelect = null;
}
return;
}
if (current) {
return;
}
const self = this;
import('../../components/multiSelect/multiSelect').then(({ default: MultiSelect }) => {
self.multiSelect = new MultiSelect({
container: self,
bindOnClick: false
});
});
function getShortcutOptions() {
return {
click: false
};
}
function onDrop(evt, itemsContainer) {
const el = evt.item;
ItemsContainerPrototype.enableMultiSelect = function (enabled) {
const current = this.multiSelect;
const newIndex = evt.newIndex;
const itemId = el.getAttribute('data-playlistitemid');
const playlistId = el.getAttribute('data-playlistid');
if (!playlistId) {
const oldIndex = evt.oldIndex;
el.dispatchEvent(new CustomEvent('itemdrop', {
detail: {
oldIndex: oldIndex,
newIndex: newIndex,
playlistItemId: itemId
},
bubbles: true,
cancelable: false
}));
return;
if (!enabled) {
if (current) {
current.destroy();
this.multiSelect = null;
}
const serverId = el.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
loading.show();
apiClient.ajax({
url: apiClient.getUrl('Playlists/' + playlistId + '/Items/' + itemId + '/Move/' + newIndex),
type: 'POST'
}).then(function () {
loading.hide();
}, function () {
loading.hide();
itemsContainer.refreshItems();
});
return;
}
ItemsContainerPrototype.enableDragReordering = function (enabled) {
const current = this.sortable;
if (!enabled) {
if (current) {
current.destroy();
this.sortable = null;
}
return;
}
if (current) {
return;
}
const self = this;
import('../../components/multiSelect/multiSelect').then(({ default: MultiSelect }) => {
self.multiSelect = new MultiSelect({
container: self,
bindOnClick: false
});
});
};
function onDrop(evt, itemsContainer) {
const el = evt.item;
const newIndex = evt.newIndex;
const itemId = el.getAttribute('data-playlistitemid');
const playlistId = el.getAttribute('data-playlistid');
if (!playlistId) {
const oldIndex = evt.oldIndex;
el.dispatchEvent(new CustomEvent('itemdrop', {
detail: {
oldIndex: oldIndex,
newIndex: newIndex,
playlistItemId: itemId
},
bubbles: true,
cancelable: false
}));
return;
}
const serverId = el.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
loading.show();
apiClient.ajax({
url: apiClient.getUrl('Playlists/' + playlistId + '/Items/' + itemId + '/Move/' + newIndex),
type: 'POST'
}).then(function () {
loading.hide();
}, function () {
loading.hide();
itemsContainer.refreshItems();
});
}
ItemsContainerPrototype.enableDragReordering = function (enabled) {
const current = this.sortable;
if (!enabled) {
if (current) {
return;
current.destroy();
this.sortable = null;
}
return;
}
const self = this;
self.sortable = new Sortable(self, {
draggable: '.listItem',
handle: '.listViewDragHandle',
if (current) {
return;
}
// dragging ended
onEnd: function (evt) {
return onDrop(evt, self);
}
});
};
const self = this;
self.sortable = new Sortable(self, {
draggable: '.listItem',
handle: '.listViewDragHandle',
function onUserDataChanged(e, apiClient, userData) {
const itemsContainer = this;
// dragging ended
onEnd: function (evt) {
return onDrop(evt, self);
}
});
};
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onUserDataChanged(userData, itemsContainer);
});
function onUserDataChanged(e, apiClient, userData) {
const itemsContainer = this;
const eventsToMonitor = getEventsToMonitor(itemsContainer);
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onUserDataChanged(userData, itemsContainer);
});
// TODO: Check user data change reason?
if (eventsToMonitor.indexOf('markfavorite') !== -1
const eventsToMonitor = getEventsToMonitor(itemsContainer);
// TODO: Check user data change reason?
if (eventsToMonitor.indexOf('markfavorite') !== -1
|| eventsToMonitor.indexOf('markplayed') !== -1
) {
itemsContainer.notifyRefreshNeeded();
}
}
function getEventsToMonitor(itemsContainer) {
const monitor = itemsContainer.getAttribute('data-monitor');
if (monitor) {
return monitor.split(',');
}
return [];
}
function onTimerCreated(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
const programId = data.ProgramId;
// This could be null, not supported by all tv providers
const newTimerId = data.Id;
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onTimerCreated(programId, newTimerId, itemsContainer);
});
}
function onSeriesTimerCreated() {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
}
}
function onTimerCancelled(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onTimerCancelled(data.Id, itemsContainer);
});
}
function onSeriesTimerCancelled(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onSeriesTimerCancelled(data.Id, itemsContainer);
});
}
function onLibraryChanged(e, apiClient, data) {
const itemsContainer = this;
const eventsToMonitor = getEventsToMonitor(itemsContainer);
if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) {
// yes this is an assumption
return;
}
const itemsAdded = data.ItemsAdded || [];
const itemsRemoved = data.ItemsRemoved || [];
if (!itemsAdded.length && !itemsRemoved.length) {
return;
}
const parentId = itemsContainer.getAttribute('data-parentid');
if (parentId) {
const foldersAddedTo = data.FoldersAddedTo || [];
const foldersRemovedFrom = data.FoldersRemovedFrom || [];
const collectionFolders = data.CollectionFolders || [];
if (foldersAddedTo.indexOf(parentId) === -1 && foldersRemovedFrom.indexOf(parentId) === -1 && collectionFolders.indexOf(parentId) === -1) {
return;
}
}
) {
itemsContainer.notifyRefreshNeeded();
}
}
function onPlaybackStopped(e, stopInfo) {
const itemsContainer = this;
const state = stopInfo.state;
function getEventsToMonitor(itemsContainer) {
const monitor = itemsContainer.getAttribute('data-monitor');
if (monitor) {
return monitor.split(',');
}
const eventsToMonitor = getEventsToMonitor(itemsContainer);
if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') {
if (eventsToMonitor.indexOf('videoplayback') !== -1) {
itemsContainer.notifyRefreshNeeded(true);
return;
}
} else if (state.NowPlayingItem?.MediaType === 'Audio' && eventsToMonitor.indexOf('audioplayback') !== -1) {
return [];
}
function onTimerCreated(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
const programId = data.ProgramId;
// This could be null, not supported by all tv providers
const newTimerId = data.Id;
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onTimerCreated(programId, newTimerId, itemsContainer);
});
}
function onSeriesTimerCreated() {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
}
}
function onTimerCancelled(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onTimerCancelled(data.Id, itemsContainer);
});
}
function onSeriesTimerCancelled(e, apiClient, data) {
const itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
import('../../components/cardbuilder/cardBuilder').then((cardBuilder) => {
cardBuilder.onSeriesTimerCancelled(data.Id, itemsContainer);
});
}
function onLibraryChanged(e, apiClient, data) {
const itemsContainer = this;
const eventsToMonitor = getEventsToMonitor(itemsContainer);
if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) {
// yes this is an assumption
return;
}
const itemsAdded = data.ItemsAdded || [];
const itemsRemoved = data.ItemsRemoved || [];
if (!itemsAdded.length && !itemsRemoved.length) {
return;
}
const parentId = itemsContainer.getAttribute('data-parentid');
if (parentId) {
const foldersAddedTo = data.FoldersAddedTo || [];
const foldersRemovedFrom = data.FoldersRemovedFrom || [];
const collectionFolders = data.CollectionFolders || [];
if (foldersAddedTo.indexOf(parentId) === -1 && foldersRemovedFrom.indexOf(parentId) === -1 && collectionFolders.indexOf(parentId) === -1) {
return;
}
}
itemsContainer.notifyRefreshNeeded();
}
function onPlaybackStopped(e, stopInfo) {
const itemsContainer = this;
const state = stopInfo.state;
const eventsToMonitor = getEventsToMonitor(itemsContainer);
if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') {
if (eventsToMonitor.indexOf('videoplayback') !== -1) {
itemsContainer.notifyRefreshNeeded(true);
return;
}
} else if (state.NowPlayingItem?.MediaType === 'Audio' && eventsToMonitor.indexOf('audioplayback') !== -1) {
itemsContainer.notifyRefreshNeeded(true);
return;
}
}
function addNotificationEvent(instance, name, handler, owner) {
const localHandler = handler.bind(instance);
function addNotificationEvent(instance, name, handler, owner) {
const localHandler = handler.bind(instance);
owner = owner || serverNotifications;
Events.on(owner, name, localHandler);
instance['event_' + name] = localHandler;
}
function removeNotificationEvent(instance, name, owner) {
const handler = instance['event_' + name];
if (handler) {
owner = owner || serverNotifications;
Events.on(owner, name, localHandler);
instance['event_' + name] = localHandler;
Events.off(owner, name, handler);
instance['event_' + name] = null;
}
}
function removeNotificationEvent(instance, name, owner) {
const handler = instance['event_' + name];
if (handler) {
owner = owner || serverNotifications;
Events.off(owner, name, handler);
instance['event_' + name] = null;
ItemsContainerPrototype.createdCallback = function () {
this.classList.add('itemsContainer');
};
ItemsContainerPrototype.attachedCallback = function () {
this.addEventListener('click', onClick);
if (browser.touch) {
this.addEventListener('contextmenu', disableEvent);
} else {
if (this.getAttribute('data-contextmenu') !== 'false') {
this.addEventListener('contextmenu', onContextMenu);
}
}
ItemsContainerPrototype.createdCallback = function () {
this.classList.add('itemsContainer');
};
if (layoutManager.desktop || layoutManager.mobile && this.getAttribute('data-multiselect') !== 'false') {
this.enableMultiSelect(true);
}
ItemsContainerPrototype.attachedCallback = function () {
this.addEventListener('click', onClick);
if (layoutManager.tv) {
this.classList.add('itemsContainer-tv');
}
if (browser.touch) {
this.addEventListener('contextmenu', disableEvent);
itemShortcuts.on(this, getShortcutOptions());
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
addNotificationEvent(this, 'TimerCreated', onTimerCreated);
addNotificationEvent(this, 'SeriesTimerCreated', onSeriesTimerCreated);
addNotificationEvent(this, 'TimerCancelled', onTimerCancelled);
addNotificationEvent(this, 'SeriesTimerCancelled', onSeriesTimerCancelled);
addNotificationEvent(this, 'LibraryChanged', onLibraryChanged);
addNotificationEvent(this, 'playbackstop', onPlaybackStopped, playbackManager);
if (this.getAttribute('data-dragreorder') === 'true') {
this.enableDragReordering(true);
}
};
ItemsContainerPrototype.detachedCallback = function () {
clearRefreshInterval(this);
this.enableMultiSelect(false);
this.enableDragReordering(false);
this.removeEventListener('click', onClick);
this.removeEventListener('contextmenu', onContextMenu);
this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions());
removeNotificationEvent(this, 'UserDataChanged');
removeNotificationEvent(this, 'TimerCreated');
removeNotificationEvent(this, 'SeriesTimerCreated');
removeNotificationEvent(this, 'TimerCancelled');
removeNotificationEvent(this, 'SeriesTimerCancelled');
removeNotificationEvent(this, 'LibraryChanged');
removeNotificationEvent(this, 'playbackstop', playbackManager);
this.fetchData = null;
this.getItemsHtml = null;
this.parentContainer = null;
};
ItemsContainerPrototype.pause = function () {
clearRefreshInterval(this, true);
this.paused = true;
};
ItemsContainerPrototype.resume = function (options) {
this.paused = false;
const refreshIntervalEndTime = this.refreshIntervalEndTime;
if (refreshIntervalEndTime) {
const remainingMs = refreshIntervalEndTime - new Date().getTime();
if (remainingMs > 0 && !this.needsRefresh) {
resetRefreshInterval(this, remainingMs);
} else {
if (this.getAttribute('data-contextmenu') !== 'false') {
this.addEventListener('contextmenu', onContextMenu);
}
this.needsRefresh = true;
this.refreshIntervalEndTime = null;
}
}
if (layoutManager.desktop || layoutManager.mobile && this.getAttribute('data-multiselect') !== 'false') {
this.enableMultiSelect(true);
}
if (this.needsRefresh || (options && options.refresh)) {
return this.refreshItems();
}
if (layoutManager.tv) {
this.classList.add('itemsContainer-tv');
}
itemShortcuts.on(this, getShortcutOptions());
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
addNotificationEvent(this, 'TimerCreated', onTimerCreated);
addNotificationEvent(this, 'SeriesTimerCreated', onSeriesTimerCreated);
addNotificationEvent(this, 'TimerCancelled', onTimerCancelled);
addNotificationEvent(this, 'SeriesTimerCancelled', onSeriesTimerCancelled);
addNotificationEvent(this, 'LibraryChanged', onLibraryChanged);
addNotificationEvent(this, 'playbackstop', onPlaybackStopped, playbackManager);
if (this.getAttribute('data-dragreorder') === 'true') {
this.enableDragReordering(true);
}
};
ItemsContainerPrototype.detachedCallback = function () {
clearRefreshInterval(this);
this.enableMultiSelect(false);
this.enableDragReordering(false);
this.removeEventListener('click', onClick);
this.removeEventListener('contextmenu', onContextMenu);
this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions());
removeNotificationEvent(this, 'UserDataChanged');
removeNotificationEvent(this, 'TimerCreated');
removeNotificationEvent(this, 'SeriesTimerCreated');
removeNotificationEvent(this, 'TimerCancelled');
removeNotificationEvent(this, 'SeriesTimerCancelled');
removeNotificationEvent(this, 'LibraryChanged');
removeNotificationEvent(this, 'playbackstop', playbackManager);
this.fetchData = null;
this.getItemsHtml = null;
this.parentContainer = null;
};
ItemsContainerPrototype.pause = function () {
clearRefreshInterval(this, true);
this.paused = true;
};
ItemsContainerPrototype.resume = function (options) {
this.paused = false;
const refreshIntervalEndTime = this.refreshIntervalEndTime;
if (refreshIntervalEndTime) {
const remainingMs = refreshIntervalEndTime - new Date().getTime();
if (remainingMs > 0 && !this.needsRefresh) {
resetRefreshInterval(this, remainingMs);
} else {
this.needsRefresh = true;
this.refreshIntervalEndTime = null;
}
}
if (this.needsRefresh || (options && options.refresh)) {
return this.refreshItems();
}
return Promise.resolve();
};
ItemsContainerPrototype.refreshItems = function () {
if (!this.fetchData) {
return Promise.resolve();
};
}
ItemsContainerPrototype.refreshItems = function () {
if (!this.fetchData) {
return Promise.resolve();
if (this.paused) {
this.needsRefresh = true;
return Promise.resolve();
}
this.needsRefresh = false;
return this.fetchData().then(onDataFetched.bind(this));
};
ItemsContainerPrototype.notifyRefreshNeeded = function (isInForeground) {
if (this.paused) {
this.needsRefresh = true;
return;
}
const timeout = this.refreshTimeout;
if (timeout) {
clearTimeout(timeout);
}
if (isInForeground === true) {
this.refreshItems();
} else {
this.refreshTimeout = setTimeout(this.refreshItems.bind(this), 10000);
}
};
function clearRefreshInterval(itemsContainer, isPausing) {
if (itemsContainer.refreshInterval) {
clearInterval(itemsContainer.refreshInterval);
itemsContainer.refreshInterval = null;
if (!isPausing) {
itemsContainer.refreshIntervalEndTime = null;
}
}
}
if (this.paused) {
this.needsRefresh = true;
return Promise.resolve();
}
function resetRefreshInterval(itemsContainer, intervalMs) {
clearRefreshInterval(itemsContainer);
this.needsRefresh = false;
if (!intervalMs) {
intervalMs = parseInt(itemsContainer.getAttribute('data-refreshinterval') || '0', 10);
}
return this.fetchData().then(onDataFetched.bind(this));
};
if (intervalMs) {
itemsContainer.refreshInterval = setInterval(itemsContainer.notifyRefreshNeeded.bind(itemsContainer), intervalMs);
itemsContainer.refreshIntervalEndTime = new Date().getTime() + intervalMs;
}
}
ItemsContainerPrototype.notifyRefreshNeeded = function (isInForeground) {
if (this.paused) {
this.needsRefresh = true;
return;
}
function onDataFetched(result) {
const items = result.Items || result;
const timeout = this.refreshTimeout;
if (timeout) {
clearTimeout(timeout);
}
if (isInForeground === true) {
this.refreshItems();
const parentContainer = this.parentContainer;
if (parentContainer) {
if (items.length) {
parentContainer.classList.remove('hide');
} else {
this.refreshTimeout = setTimeout(this.refreshItems.bind(this), 10000);
parentContainer.classList.add('hide');
}
};
}
function clearRefreshInterval(itemsContainer, isPausing) {
if (itemsContainer.refreshInterval) {
clearInterval(itemsContainer.refreshInterval);
itemsContainer.refreshInterval = null;
const activeElement = document.activeElement;
let focusId;
let hasActiveElement;
if (!isPausing) {
itemsContainer.refreshIntervalEndTime = null;
if (this.contains(activeElement)) {
hasActiveElement = true;
focusId = activeElement.getAttribute('data-id');
}
this.innerHTML = this.getItemsHtml(items);
imageLoader.lazyChildren(this);
if (hasActiveElement) {
setFocus(this, focusId);
}
resetRefreshInterval(this);
if (this.afterRefresh) {
this.afterRefresh(result);
}
}
function setFocus(itemsContainer, focusId) {
if (focusId) {
const newElement = itemsContainer.querySelector('[data-id="' + focusId + '"]');
if (newElement) {
try {
focusManager.focus(newElement);
return;
} catch (err) {
console.error(err);
}
}
}
function resetRefreshInterval(itemsContainer, intervalMs) {
clearRefreshInterval(itemsContainer);
focusManager.autoFocus(itemsContainer);
}
if (!intervalMs) {
intervalMs = parseInt(itemsContainer.getAttribute('data-refreshinterval') || '0', 10);
}
document.registerElement('emby-itemscontainer', {
prototype: ItemsContainerPrototype,
extends: 'div'
});
if (intervalMs) {
itemsContainer.refreshInterval = setInterval(itemsContainer.notifyRefreshNeeded.bind(itemsContainer), intervalMs);
itemsContainer.refreshIntervalEndTime = new Date().getTime() + intervalMs;
}
}
function onDataFetched(result) {
const items = result.Items || result;
const parentContainer = this.parentContainer;
if (parentContainer) {
if (items.length) {
parentContainer.classList.remove('hide');
} else {
parentContainer.classList.add('hide');
}
}
const activeElement = document.activeElement;
let focusId;
let hasActiveElement;
if (this.contains(activeElement)) {
hasActiveElement = true;
focusId = activeElement.getAttribute('data-id');
}
this.innerHTML = this.getItemsHtml(items);
imageLoader.lazyChildren(this);
if (hasActiveElement) {
setFocus(this, focusId);
}
resetRefreshInterval(this);
if (this.afterRefresh) {
this.afterRefresh(result);
}
}
function setFocus(itemsContainer, focusId) {
if (focusId) {
const newElement = itemsContainer.querySelector('[data-id="' + focusId + '"]');
if (newElement) {
try {
focusManager.focus(newElement);
return;
} catch (err) {
console.error(err);
}
}
}
focusManager.autoFocus(itemsContainer);
}
document.registerElement('emby-itemscontainer', {
prototype: ItemsContainerPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -4,151 +4,148 @@ import Events from '../../utils/events.ts';
import EmbyButtonPrototype from '../../elements/emby-button/emby-button';
import ServerConnections from '../../components/ServerConnections';
/* eslint-disable indent */
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
}
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
}
}
function onClick() {
const button = this;
const id = button.getAttribute('data-id');
const serverId = button.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
if (!button.classList.contains('playstatebutton-played')) {
apiClient.markPlayed(apiClient.getCurrentUserId(), id, new Date());
setState(button, true);
} else {
apiClient.markUnplayed(apiClient.getCurrentUserId(), id, new Date());
setState(button, false);
}
}
function onUserDataChanged(e, apiClient, userData) {
const button = this;
if (userData.ItemId === button.getAttribute('data-id')) {
setState(button, userData.Played);
}
}
function setState(button, played, updateAttribute) {
let icon = button.iconElement;
if (!icon) {
button.iconElement = button.querySelector('.material-icons');
icon = button.iconElement;
}
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
if (played) {
button.classList.add('playstatebutton-played');
if (icon) {
icon.classList.add('playstatebutton-icon-played');
icon.classList.remove('playstatebutton-icon-unplayed');
}
} else {
button.classList.remove('playstatebutton-played');
if (icon) {
icon.classList.remove('playstatebutton-icon-played');
icon.classList.add('playstatebutton-icon-unplayed');
}
}
function onClick() {
const button = this;
const id = button.getAttribute('data-id');
const serverId = button.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
if (!button.classList.contains('playstatebutton-played')) {
apiClient.markPlayed(apiClient.getCurrentUserId(), id, new Date());
setState(button, true);
} else {
apiClient.markUnplayed(apiClient.getCurrentUserId(), id, new Date());
setState(button, false);
}
if (updateAttribute !== false) {
button.setAttribute('data-played', played);
}
function onUserDataChanged(e, apiClient, userData) {
const button = this;
if (userData.ItemId === button.getAttribute('data-id')) {
setState(button, userData.Played);
}
setTitle(button, button.getAttribute('data-type'), played);
}
function setTitle(button, itemType, played) {
if (itemType !== 'AudioBook' && itemType !== 'AudioPodcast') {
button.title = played ? globalize.translate('Watched') : globalize.translate('MarkPlayed');
} else {
button.title = played ? globalize.translate('Played') : globalize.translate('MarkPlayed');
}
function setState(button, played, updateAttribute) {
let icon = button.iconElement;
if (!icon) {
button.iconElement = button.querySelector('.material-icons');
icon = button.iconElement;
}
const text = button.querySelector('.button-text');
if (text) {
text.innerText = button.title;
}
}
if (played) {
button.classList.add('playstatebutton-played');
if (icon) {
icon.classList.add('playstatebutton-icon-played');
icon.classList.remove('playstatebutton-icon-unplayed');
}
} else {
button.classList.remove('playstatebutton-played');
if (icon) {
icon.classList.remove('playstatebutton-icon-played');
icon.classList.add('playstatebutton-icon-unplayed');
}
}
function clearEvents(button) {
button.removeEventListener('click', onClick);
removeNotificationEvent(button, 'UserDataChanged');
}
if (updateAttribute !== false) {
button.setAttribute('data-played', played);
}
function bindEvents(button) {
clearEvents(button);
setTitle(button, button.getAttribute('data-type'), played);
button.addEventListener('click', onClick);
addNotificationEvent(button, 'UserDataChanged', onUserDataChanged);
}
const EmbyPlaystateButtonPrototype = Object.create(EmbyButtonPrototype);
EmbyPlaystateButtonPrototype.createdCallback = function () {
// base method
if (EmbyButtonPrototype.createdCallback) {
EmbyButtonPrototype.createdCallback.call(this);
}
};
EmbyPlaystateButtonPrototype.attachedCallback = function () {
// base method
if (EmbyButtonPrototype.attachedCallback) {
EmbyButtonPrototype.attachedCallback.call(this);
}
function setTitle(button, itemType, played) {
if (itemType !== 'AudioBook' && itemType !== 'AudioPodcast') {
button.title = played ? globalize.translate('Watched') : globalize.translate('MarkPlayed');
} else {
button.title = played ? globalize.translate('Played') : globalize.translate('MarkPlayed');
}
const itemId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
if (itemId && serverId) {
setState(this, this.getAttribute('data-played') === 'true', false);
bindEvents(this);
}
};
const text = button.querySelector('.button-text');
if (text) {
text.innerText = button.title;
}
EmbyPlaystateButtonPrototype.detachedCallback = function () {
// base method
if (EmbyButtonPrototype.detachedCallback) {
EmbyButtonPrototype.detachedCallback.call(this);
}
function clearEvents(button) {
button.removeEventListener('click', onClick);
removeNotificationEvent(button, 'UserDataChanged');
}
clearEvents(this);
this.iconElement = null;
};
function bindEvents(button) {
clearEvents(button);
button.addEventListener('click', onClick);
addNotificationEvent(button, 'UserDataChanged', onUserDataChanged);
}
const EmbyPlaystateButtonPrototype = Object.create(EmbyButtonPrototype);
EmbyPlaystateButtonPrototype.createdCallback = function () {
// base method
if (EmbyButtonPrototype.createdCallback) {
EmbyButtonPrototype.createdCallback.call(this);
}
};
EmbyPlaystateButtonPrototype.attachedCallback = function () {
// base method
if (EmbyButtonPrototype.attachedCallback) {
EmbyButtonPrototype.attachedCallback.call(this);
}
const itemId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
if (itemId && serverId) {
setState(this, this.getAttribute('data-played') === 'true', false);
bindEvents(this);
}
};
EmbyPlaystateButtonPrototype.detachedCallback = function () {
// base method
if (EmbyButtonPrototype.detachedCallback) {
EmbyButtonPrototype.detachedCallback.call(this);
}
EmbyPlaystateButtonPrototype.setItem = function (item) {
if (item) {
this.setAttribute('data-id', item.Id);
this.setAttribute('data-serverid', item.ServerId);
this.setAttribute('data-type', item.Type);
const played = item.UserData && item.UserData.Played;
setState(this, played);
bindEvents(this);
} else {
this.removeAttribute('data-id');
this.removeAttribute('data-serverid');
this.removeAttribute('data-type');
this.removeAttribute('data-played');
clearEvents(this);
this.iconElement = null;
};
}
};
EmbyPlaystateButtonPrototype.setItem = function (item) {
if (item) {
this.setAttribute('data-id', item.Id);
this.setAttribute('data-serverid', item.ServerId);
this.setAttribute('data-type', item.Type);
document.registerElement('emby-playstatebutton', {
prototype: EmbyPlaystateButtonPrototype,
extends: 'button'
});
const played = item.UserData && item.UserData.Played;
setState(this, played);
bindEvents(this);
} else {
this.removeAttribute('data-id');
this.removeAttribute('data-serverid');
this.removeAttribute('data-type');
this.removeAttribute('data-played');
clearEvents(this);
}
};
document.registerElement('emby-playstatebutton', {
prototype: EmbyPlaystateButtonPrototype,
extends: 'button'
});
/* eslint-enable indent */

View file

@ -1,42 +1,40 @@
/* eslint-disable indent */
const ProgressBarPrototype = Object.create(HTMLDivElement.prototype);
const ProgressBarPrototype = Object.create(HTMLDivElement.prototype);
function onAutoTimeProgress() {
const start = parseInt(this.getAttribute('data-starttime'), 10);
const end = parseInt(this.getAttribute('data-endtime'), 10);
function onAutoTimeProgress() {
const start = parseInt(this.getAttribute('data-starttime'), 10);
const end = parseInt(this.getAttribute('data-endtime'), 10);
const now = new Date().getTime();
const total = end - start;
let pct = 100 * ((now - start) / total);
const now = new Date().getTime();
const total = end - start;
let pct = 100 * ((now - start) / total);
pct = Math.min(100, pct);
pct = Math.max(0, pct);
pct = Math.min(100, pct);
pct = Math.max(0, pct);
const itemProgressBarForeground = this.querySelector('.itemProgressBarForeground');
itemProgressBarForeground.style.width = pct + '%';
const itemProgressBarForeground = this.querySelector('.itemProgressBarForeground');
itemProgressBarForeground.style.width = pct + '%';
}
ProgressBarPrototype.attachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
}
ProgressBarPrototype.attachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
}
if (this.getAttribute('data-automode') === 'time') {
this.timeInterval = setInterval(onAutoTimeProgress.bind(this), 60000);
}
};
if (this.getAttribute('data-automode') === 'time') {
this.timeInterval = setInterval(onAutoTimeProgress.bind(this), 60000);
}
};
ProgressBarPrototype.detachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
this.timeInterval = null;
}
};
ProgressBarPrototype.detachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
this.timeInterval = null;
}
};
document.registerElement('emby-progressbar', {
prototype: ProgressBarPrototype,
extends: 'div'
});
document.registerElement('emby-progressbar', {
prototype: ProgressBarPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -4,98 +4,95 @@ import template from './emby-progressring.template.html';
import { getCurrentDateTimeLocale } from '../../scripts/globalize';
import { toPercent } from '../../utils/number.ts';
/* eslint-disable indent */
const EmbyProgressRing = Object.create(HTMLDivElement.prototype);
const EmbyProgressRing = Object.create(HTMLDivElement.prototype);
EmbyProgressRing.createdCallback = function () {
this.classList.add('progressring');
this.setAttribute('dir', 'ltr');
const instance = this;
EmbyProgressRing.createdCallback = function () {
this.classList.add('progressring');
this.setAttribute('dir', 'ltr');
const instance = this;
instance.innerHTML = template;
instance.innerHTML = template;
if (window.MutationObserver) {
// create an observer instance
const observer = new MutationObserver(function (mutations) {
mutations.forEach(function () {
instance.setProgress(parseFloat(instance.getAttribute('data-progress') || '0'));
});
if (window.MutationObserver) {
// create an observer instance
const observer = new MutationObserver(function (mutations) {
mutations.forEach(function () {
instance.setProgress(parseFloat(instance.getAttribute('data-progress') || '0'));
});
});
// configuration of the observer:
const config = { attributes: true, childList: false, characterData: false };
// configuration of the observer:
const config = { attributes: true, childList: false, characterData: false };
// pass in the target node, as well as the observer options
observer.observe(instance, config);
// pass in the target node, as well as the observer options
observer.observe(instance, config);
instance.observer = observer;
}
instance.observer = observer;
}
instance.setProgress(parseFloat(instance.getAttribute('data-progress') || '0'));
};
instance.setProgress(parseFloat(instance.getAttribute('data-progress') || '0'));
};
EmbyProgressRing.setProgress = function (progress) {
progress = Math.floor(progress);
EmbyProgressRing.setProgress = function (progress) {
progress = Math.floor(progress);
let angle;
let angle;
if (progress < 25) {
angle = -90 + (progress / 100) * 360;
if (progress < 25) {
angle = -90 + (progress / 100) * 360;
this.querySelector('.animate-0-25-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-0-25-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-25-50-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 25 && progress < 50) {
angle = -90 + ((progress - 25) / 100) * 360;
this.querySelector('.animate-25-50-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 25 && progress < 50) {
angle = -90 + ((progress - 25) / 100) * 360;
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 50 && progress < 75) {
angle = -90 + ((progress - 50) / 100) * 360;
this.querySelector('.animate-50-75-b').style.transform = 'rotate(-90deg)';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 50 && progress < 75) {
angle = -90 + ((progress - 50) / 100) * 360;
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'none';
this.querySelector('.animate-50-75-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'none';
this.querySelector('.animate-50-75-b').style.transform = 'rotate(' + angle + 'deg)';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 75 && progress <= 100) {
angle = -90 + ((progress - 75) / 100) * 360;
this.querySelector('.animate-75-100-b').style.transform = 'rotate(-90deg)';
} else if (progress >= 75 && progress <= 100) {
angle = -90 + ((progress - 75) / 100) * 360;
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'none';
this.querySelector('.animate-50-75-b').style.transform = 'none';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(' + angle + 'deg)';
}
this.querySelector('.animate-0-25-b').style.transform = 'none';
this.querySelector('.animate-25-50-b').style.transform = 'none';
this.querySelector('.animate-50-75-b').style.transform = 'none';
this.querySelector('.animate-75-100-b').style.transform = 'rotate(' + angle + 'deg)';
}
this.querySelector('.progressring-text').innerHTML = toPercent(progress / 100, getCurrentDateTimeLocale());
};
this.querySelector('.progressring-text').innerHTML = toPercent(progress / 100, getCurrentDateTimeLocale());
};
EmbyProgressRing.attachedCallback = function () {
// no-op
};
EmbyProgressRing.attachedCallback = function () {
// no-op
};
EmbyProgressRing.detachedCallback = function () {
const observer = this.observer;
EmbyProgressRing.detachedCallback = function () {
const observer = this.observer;
if (observer) {
// later, you can stop observing
observer.disconnect();
if (observer) {
// later, you can stop observing
observer.disconnect();
this.observer = null;
}
};
this.observer = null;
}
};
document.registerElement('emby-progressring', {
prototype: EmbyProgressRing,
extends: 'div'
});
document.registerElement('emby-progressring', {
prototype: EmbyProgressRing,
extends: 'div'
});
export default EmbyProgressRing;
export default EmbyProgressRing;
/* eslint-enable indent */

View file

@ -3,80 +3,77 @@ import browser from '../../scripts/browser';
import 'webcomponents.js/webcomponents-lite';
import './emby-radio.scss';
/* eslint-disable indent */
const EmbyRadioPrototype = Object.create(HTMLInputElement.prototype);
const EmbyRadioPrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) {
// Don't submit form on enter
// Real (non-emulator) Tizen does nothing on Space
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
e.preventDefault();
function onKeyDown(e) {
// Don't submit form on enter
// Real (non-emulator) Tizen does nothing on Space
if (e.keyCode === 13 || (e.keyCode === 32 && browser.tizen)) {
e.preventDefault();
if (!this.checked) {
this.checked = true;
if (!this.checked) {
this.checked = true;
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
}
return false;
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
}
return false;
}
}
EmbyRadioPrototype.attachedCallback = function () {
const showFocus = !layoutManager.mobile;
if (this.getAttribute('data-radio') === 'true') {
return;
}
EmbyRadioPrototype.attachedCallback = function () {
const showFocus = !layoutManager.mobile;
this.setAttribute('data-radio', 'true');
if (this.getAttribute('data-radio') === 'true') {
return;
}
this.classList.add('mdl-radio__button');
this.setAttribute('data-radio', 'true');
const labelElement = this.parentNode;
labelElement.classList.add('mdl-radio');
labelElement.classList.add('mdl-js-radio');
labelElement.classList.add('mdl-js-ripple-effect');
if (showFocus) {
labelElement.classList.add('show-focus');
}
this.classList.add('mdl-radio__button');
const labelTextElement = labelElement.querySelector('span');
const labelElement = this.parentNode;
labelElement.classList.add('mdl-radio');
labelElement.classList.add('mdl-js-radio');
labelElement.classList.add('mdl-js-ripple-effect');
if (showFocus) {
labelElement.classList.add('show-focus');
}
labelTextElement.classList.add('radioButtonLabel');
labelTextElement.classList.add('mdl-radio__label');
const labelTextElement = labelElement.querySelector('span');
let html = '';
labelTextElement.classList.add('radioButtonLabel');
labelTextElement.classList.add('mdl-radio__label');
html += '<div class="mdl-radio__circles">';
let html = '';
html += '<svg>';
html += '<defs>';
html += '<clipPath id="cutoff">';
html += '<circle cx="50%" cy="50%" r="50%" />';
html += '</clipPath>';
html += '</defs>';
html += '<circle class="mdl-radio__outer-circle" cx="50%" cy="50%" r="50%" fill="none" stroke="currentcolor" stroke-width="0.26em" clip-path="url(#cutoff)" />';
html += '<circle class="mdl-radio__inner-circle" cx="50%" cy="50%" r="25%" fill="currentcolor" />';
html += '</svg>';
html += '<div class="mdl-radio__circles">';
if (showFocus) {
html += '<div class="mdl-radio__focus-circle"></div>';
}
html += '<svg>';
html += '<defs>';
html += '<clipPath id="cutoff">';
html += '<circle cx="50%" cy="50%" r="50%" />';
html += '</clipPath>';
html += '</defs>';
html += '<circle class="mdl-radio__outer-circle" cx="50%" cy="50%" r="50%" fill="none" stroke="currentcolor" stroke-width="0.26em" clip-path="url(#cutoff)" />';
html += '<circle class="mdl-radio__inner-circle" cx="50%" cy="50%" r="25%" fill="currentcolor" />';
html += '</svg>';
html += '</div>';
if (showFocus) {
html += '<div class="mdl-radio__focus-circle"></div>';
}
this.insertAdjacentHTML('afterend', html);
html += '</div>';
this.addEventListener('keydown', onKeyDown);
};
this.insertAdjacentHTML('afterend', html);
document.registerElement('emby-radio', {
prototype: EmbyRadioPrototype,
extends: 'input'
});
this.addEventListener('keydown', onKeyDown);
};
document.registerElement('emby-radio', {
prototype: EmbyRadioPrototype,
extends: 'input'
});
/* eslint-enable indent */

View file

@ -4,32 +4,119 @@ import Events from '../../utils/events.ts';
import EmbyButtonPrototype from '../emby-button/emby-button';
import ServerConnections from '../../components/ServerConnections';
/* eslint-disable indent */
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
}
function addNotificationEvent(instance, name, handler) {
const localHandler = handler.bind(instance);
Events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
}
}
function showPicker(button, apiClient, itemId, likes, isFavorite) {
return apiClient.updateFavoriteStatus(apiClient.getCurrentUserId(), itemId, !isFavorite);
}
function onClick() {
const button = this;
const id = button.getAttribute('data-id');
const serverId = button.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
let likes = this.getAttribute('data-likes');
const isFavorite = this.getAttribute('data-isfavorite') === 'true';
if (likes === 'true') {
likes = true;
} else if (likes === 'false') {
likes = false;
} else {
likes = null;
}
function removeNotificationEvent(instance, name) {
const handler = instance[name];
if (handler) {
Events.off(serverNotifications, name, handler);
instance[name] = null;
showPicker(button, apiClient, id, likes, isFavorite).then(function (userData) {
setState(button, userData.Likes, userData.IsFavorite);
});
}
function onUserDataChanged(e, apiClient, userData) {
const button = this;
if (userData.ItemId === button.getAttribute('data-id')) {
setState(button, userData.Likes, userData.IsFavorite);
}
}
function setState(button, likes, isFavorite, updateAttribute) {
const icon = button.querySelector('.material-icons');
if (isFavorite) {
if (icon) {
icon.classList.add('favorite');
icon.classList.add('ratingbutton-icon-withrating');
}
button.classList.add('ratingbutton-withrating');
} else {
if (icon) {
icon.classList.add('favorite');
icon.classList.remove('ratingbutton-icon-withrating');
}
button.classList.remove('ratingbutton-withrating');
}
function showPicker(button, apiClient, itemId, likes, isFavorite) {
return apiClient.updateFavoriteStatus(apiClient.getCurrentUserId(), itemId, !isFavorite);
if (updateAttribute !== false) {
button.setAttribute('data-isfavorite', isFavorite);
button.setAttribute('data-likes', (likes === null ? '' : likes));
}
function onClick() {
const button = this;
const id = button.getAttribute('data-id');
const serverId = button.getAttribute('data-serverid');
const apiClient = ServerConnections.getApiClient(serverId);
setTitle(button, isFavorite);
}
function setTitle(button, isFavorite) {
button.title = isFavorite ? globalize.translate('Favorite') : globalize.translate('AddToFavorites');
const text = button.querySelector('.button-text');
if (text) {
text.innerText = button.title;
}
}
function clearEvents(button) {
button.removeEventListener('click', onClick);
removeNotificationEvent(button, 'UserDataChanged');
}
function bindEvents(button) {
clearEvents(button);
button.addEventListener('click', onClick);
addNotificationEvent(button, 'UserDataChanged', onUserDataChanged);
}
const EmbyRatingButtonPrototype = Object.create(EmbyButtonPrototype);
EmbyRatingButtonPrototype.createdCallback = function () {
// base method
if (EmbyButtonPrototype.createdCallback) {
EmbyButtonPrototype.createdCallback.call(this);
}
};
EmbyRatingButtonPrototype.attachedCallback = function () {
// base method
if (EmbyButtonPrototype.attachedCallback) {
EmbyButtonPrototype.attachedCallback.call(this);
}
const itemId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
if (itemId && serverId) {
let likes = this.getAttribute('data-likes');
const isFavorite = this.getAttribute('data-isfavorite') === 'true';
if (likes === 'true') {
@ -40,131 +127,41 @@ import ServerConnections from '../../components/ServerConnections';
likes = null;
}
showPicker(button, apiClient, id, likes, isFavorite).then(function (userData) {
setState(button, userData.Likes, userData.IsFavorite);
});
setState(this, likes, isFavorite, false);
bindEvents(this);
} else {
setTitle(this);
}
};
EmbyRatingButtonPrototype.detachedCallback = function () {
// base method
if (EmbyButtonPrototype.detachedCallback) {
EmbyButtonPrototype.detachedCallback.call(this);
}
function onUserDataChanged(e, apiClient, userData) {
const button = this;
clearEvents(this);
};
if (userData.ItemId === button.getAttribute('data-id')) {
setState(button, userData.Likes, userData.IsFavorite);
}
}
function setState(button, likes, isFavorite, updateAttribute) {
const icon = button.querySelector('.material-icons');
if (isFavorite) {
if (icon) {
icon.classList.add('favorite');
icon.classList.add('ratingbutton-icon-withrating');
}
button.classList.add('ratingbutton-withrating');
} else {
if (icon) {
icon.classList.add('favorite');
icon.classList.remove('ratingbutton-icon-withrating');
}
button.classList.remove('ratingbutton-withrating');
}
if (updateAttribute !== false) {
button.setAttribute('data-isfavorite', isFavorite);
button.setAttribute('data-likes', (likes === null ? '' : likes));
}
setTitle(button, isFavorite);
}
function setTitle(button, isFavorite) {
button.title = isFavorite ? globalize.translate('Favorite') : globalize.translate('AddToFavorites');
const text = button.querySelector('.button-text');
if (text) {
text.innerText = button.title;
}
}
function clearEvents(button) {
button.removeEventListener('click', onClick);
removeNotificationEvent(button, 'UserDataChanged');
}
function bindEvents(button) {
clearEvents(button);
button.addEventListener('click', onClick);
addNotificationEvent(button, 'UserDataChanged', onUserDataChanged);
}
const EmbyRatingButtonPrototype = Object.create(EmbyButtonPrototype);
EmbyRatingButtonPrototype.createdCallback = function () {
// base method
if (EmbyButtonPrototype.createdCallback) {
EmbyButtonPrototype.createdCallback.call(this);
}
};
EmbyRatingButtonPrototype.attachedCallback = function () {
// base method
if (EmbyButtonPrototype.attachedCallback) {
EmbyButtonPrototype.attachedCallback.call(this);
}
const itemId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
if (itemId && serverId) {
let likes = this.getAttribute('data-likes');
const isFavorite = this.getAttribute('data-isfavorite') === 'true';
if (likes === 'true') {
likes = true;
} else if (likes === 'false') {
likes = false;
} else {
likes = null;
}
setState(this, likes, isFavorite, false);
bindEvents(this);
} else {
setTitle(this);
}
};
EmbyRatingButtonPrototype.detachedCallback = function () {
// base method
if (EmbyButtonPrototype.detachedCallback) {
EmbyButtonPrototype.detachedCallback.call(this);
}
EmbyRatingButtonPrototype.setItem = function (item) {
if (item) {
this.setAttribute('data-id', item.Id);
this.setAttribute('data-serverid', item.ServerId);
const userData = item.UserData || {};
setState(this, userData.Likes, userData.IsFavorite);
bindEvents(this);
} else {
this.removeAttribute('data-id');
this.removeAttribute('data-serverid');
this.removeAttribute('data-likes');
this.removeAttribute('data-isfavorite');
clearEvents(this);
};
}
};
EmbyRatingButtonPrototype.setItem = function (item) {
if (item) {
this.setAttribute('data-id', item.Id);
this.setAttribute('data-serverid', item.ServerId);
document.registerElement('emby-ratingbutton', {
prototype: EmbyRatingButtonPrototype,
extends: 'button'
});
const userData = item.UserData || {};
setState(this, userData.Likes, userData.IsFavorite);
bindEvents(this);
} else {
this.removeAttribute('data-id');
this.removeAttribute('data-serverid');
this.removeAttribute('data-likes');
this.removeAttribute('data-isfavorite');
clearEvents(this);
}
};
document.registerElement('emby-ratingbutton', {
prototype: EmbyRatingButtonPrototype,
extends: 'button'
});
/* eslint-enable indent */

View file

@ -3,198 +3,195 @@ import 'webcomponents.js/webcomponents-lite';
import '../emby-button/paper-icon-button-light';
import globalize from '../../scripts/globalize';
/* eslint-disable indent */
const EmbyScrollButtonsPrototype = Object.create(HTMLDivElement.prototype);
EmbyScrollButtonsPrototype.createdCallback = function () {
// no-op
};
EmbyScrollButtonsPrototype.createdCallback = function () {
// no-op
};
function getScrollButtonHtml(direction) {
let html = '';
const icon = direction === 'left' ? 'chevron_left' : 'chevron_right';
const title = direction === 'left' ? globalize.translate('Previous') : globalize.translate('Next') ;
function getScrollButtonHtml(direction) {
let html = '';
const icon = direction === 'left' ? 'chevron_left' : 'chevron_right';
const title = direction === 'left' ? globalize.translate('Previous') : globalize.translate('Next') ;
html += `<button type="button" is="paper-icon-button-light" data-ripple="false" data-direction="${direction}" title="${title}" class="emby-scrollbuttons-button">`;
html += '<span class="material-icons ' + icon + '" aria-hidden="true"></span>';
html += '</button>';
html += `<button type="button" is="paper-icon-button-light" data-ripple="false" data-direction="${direction}" title="${title}" class="emby-scrollbuttons-button">`;
html += '<span class="material-icons ' + icon + '" aria-hidden="true"></span>';
html += '</button>';
return html;
return html;
}
function getScrollPosition(parent) {
if (parent.getScrollPosition) {
return parent.getScrollPosition();
}
function getScrollPosition(parent) {
if (parent.getScrollPosition) {
return parent.getScrollPosition();
}
return 0;
}
function getScrollWidth(parent) {
if (parent.getScrollSize) {
return parent.getScrollSize();
}
return 0;
}
function updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth) {
let localeAwarePos = scrollPos;
if (globalize.getIsElementRTL(scrollButtons)) {
localeAwarePos *= -1;
}
// TODO: Check if hack is really needed
// hack alert add twenty for rounding errors
if (scrollWidth <= scrollSize + 20) {
scrollButtons.scrollButtonsLeft.classList.add('hide');
scrollButtons.scrollButtonsRight.classList.add('hide');
} else {
scrollButtons.scrollButtonsLeft.classList.remove('hide');
scrollButtons.scrollButtonsRight.classList.remove('hide');
}
if (localeAwarePos > 0) {
scrollButtons.scrollButtonsLeft.disabled = false;
} else {
scrollButtons.scrollButtonsLeft.disabled = true;
}
const scrollPosEnd = localeAwarePos + scrollSize;
if (scrollWidth > 0 && scrollPosEnd >= scrollWidth) {
scrollButtons.scrollButtonsRight.disabled = true;
} else {
scrollButtons.scrollButtonsRight.disabled = false;
}
}
function onScroll() {
const scrollButtons = this;
const scroller = this.scroller;
const scrollSize = getScrollSize(scroller);
const scrollPos = getScrollPosition(scroller);
const scrollWidth = getScrollWidth(scroller);
updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth);
}
function getStyleValue(style, name) {
let value = style.getPropertyValue(name);
if (!value) {
return 0;
}
function getScrollWidth(parent) {
if (parent.getScrollSize) {
return parent.getScrollSize();
}
value = value.replace('px', '');
if (!value) {
return 0;
}
function updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth) {
let localeAwarePos = scrollPos;
if (globalize.getIsElementRTL(scrollButtons)) {
localeAwarePos *= -1;
}
// TODO: Check if hack is really needed
// hack alert add twenty for rounding errors
if (scrollWidth <= scrollSize + 20) {
scrollButtons.scrollButtonsLeft.classList.add('hide');
scrollButtons.scrollButtonsRight.classList.add('hide');
} else {
scrollButtons.scrollButtonsLeft.classList.remove('hide');
scrollButtons.scrollButtonsRight.classList.remove('hide');
}
if (localeAwarePos > 0) {
scrollButtons.scrollButtonsLeft.disabled = false;
} else {
scrollButtons.scrollButtonsLeft.disabled = true;
}
const scrollPosEnd = localeAwarePos + scrollSize;
if (scrollWidth > 0 && scrollPosEnd >= scrollWidth) {
scrollButtons.scrollButtonsRight.disabled = true;
} else {
scrollButtons.scrollButtonsRight.disabled = false;
}
value = parseInt(value, 10);
if (isNaN(value)) {
return 0;
}
function onScroll() {
const scrollButtons = this;
const scroller = this.scroller;
return value;
}
const scrollSize = getScrollSize(scroller);
const scrollPos = getScrollPosition(scroller);
const scrollWidth = getScrollWidth(scroller);
function getScrollSize(elem) {
let scrollSize = elem.offsetWidth;
let style = window.getComputedStyle(elem, null);
updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth);
let paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
function getStyleValue(style, name) {
let value = style.getPropertyValue(name);
if (!value) {
return 0;
}
value = value.replace('px', '');
if (!value) {
return 0;
}
value = parseInt(value, 10);
if (isNaN(value)) {
return 0;
}
return value;
let paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
function getScrollSize(elem) {
let scrollSize = elem.offsetWidth;
let style = window.getComputedStyle(elem, null);
const slider = elem.getScrollSlider();
style = window.getComputedStyle(slider, null);
let paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
let paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
const slider = elem.getScrollSlider();
style = window.getComputedStyle(slider, null);
paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
return scrollSize;
paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
function onScrollButtonClick() {
const scroller = this.parentNode.nextSibling;
const direction = this.getAttribute('data-direction');
const scrollSize = getScrollSize(scroller);
const scrollPos = getScrollPosition(scroller);
let newPos;
if (direction === 'left') {
newPos = Math.max(0, scrollPos - scrollSize);
} else {
newPos = scrollPos + scrollSize;
}
if (globalize.getIsRTL() && direction === 'left') {
newPos = scrollPos + scrollSize;
} else if (globalize.getIsRTL()) {
newPos = Math.min(0, scrollPos - scrollSize);
}
scroller.scrollToPosition(newPos, false);
paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
EmbyScrollButtonsPrototype.attachedCallback = function () {
const scroller = this.nextSibling;
this.scroller = scroller;
return scrollSize;
}
const parent = this.parentNode;
parent.classList.add('emby-scroller-container');
function onScrollButtonClick() {
const scroller = this.parentNode.nextSibling;
this.innerHTML = getScrollButtonHtml('left') + getScrollButtonHtml('right');
const direction = this.getAttribute('data-direction');
const scrollSize = getScrollSize(scroller);
const scrollPos = getScrollPosition(scroller);
const buttons = this.querySelectorAll('.emby-scrollbuttons-button');
buttons[0].addEventListener('click', onScrollButtonClick);
buttons[1].addEventListener('click', onScrollButtonClick);
this.scrollButtonsLeft = buttons[0];
this.scrollButtonsRight = buttons[1];
let newPos;
if (direction === 'left') {
newPos = Math.max(0, scrollPos - scrollSize);
} else {
newPos = scrollPos + scrollSize;
}
const scrollHandler = onScroll.bind(this);
this.scrollHandler = scrollHandler;
scroller.addScrollEventListener(scrollHandler, {
if (globalize.getIsRTL() && direction === 'left') {
newPos = scrollPos + scrollSize;
} else if (globalize.getIsRTL()) {
newPos = Math.min(0, scrollPos - scrollSize);
}
scroller.scrollToPosition(newPos, false);
}
EmbyScrollButtonsPrototype.attachedCallback = function () {
const scroller = this.nextSibling;
this.scroller = scroller;
const parent = this.parentNode;
parent.classList.add('emby-scroller-container');
this.innerHTML = getScrollButtonHtml('left') + getScrollButtonHtml('right');
const buttons = this.querySelectorAll('.emby-scrollbuttons-button');
buttons[0].addEventListener('click', onScrollButtonClick);
buttons[1].addEventListener('click', onScrollButtonClick);
this.scrollButtonsLeft = buttons[0];
this.scrollButtonsRight = buttons[1];
const scrollHandler = onScroll.bind(this);
this.scrollHandler = scrollHandler;
scroller.addScrollEventListener(scrollHandler, {
capture: false,
passive: true
});
};
EmbyScrollButtonsPrototype.detachedCallback = function () {
const parent = this.scroller;
this.scroller = null;
const scrollHandler = this.scrollHandler;
if (parent && scrollHandler) {
parent.removeScrollEventListener(scrollHandler, {
capture: false,
passive: true
});
};
}
EmbyScrollButtonsPrototype.detachedCallback = function () {
const parent = this.scroller;
this.scroller = null;
this.scrollHandler = null;
this.scrollButtonsLeft = null;
this.scrollButtonsRight = null;
};
const scrollHandler = this.scrollHandler;
if (parent && scrollHandler) {
parent.removeScrollEventListener(scrollHandler, {
capture: false,
passive: true
});
}
document.registerElement('emby-scrollbuttons', {
prototype: EmbyScrollButtonsPrototype,
extends: 'div'
});
this.scrollHandler = null;
this.scrollButtonsLeft = null;
this.scrollButtonsRight = null;
};
document.registerElement('emby-scrollbuttons', {
prototype: EmbyScrollButtonsPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -7,195 +7,192 @@ import browser from '../../scripts/browser';
import 'webcomponents.js/webcomponents-lite';
import './emby-scroller.scss';
/* eslint-disable indent */
const ScrollerPrototype = Object.create(HTMLDivElement.prototype);
const ScrollerPrototype = Object.create(HTMLDivElement.prototype);
ScrollerPrototype.createdCallback = function () {
this.classList.add('emby-scroller');
};
ScrollerPrototype.createdCallback = function () {
this.classList.add('emby-scroller');
};
function initCenterFocus(elem, scrollerInstance) {
dom.addEventListener(elem, 'focus', function (e) {
const focused = focusManager.focusableParent(e.target);
if (focused) {
scrollerInstance.toCenter(focused);
}
}, {
capture: true,
passive: true
});
}
ScrollerPrototype.scrollToBeginning = function () {
if (this.scroller) {
this.scroller.slideTo(0, true);
function initCenterFocus(elem, scrollerInstance) {
dom.addEventListener(elem, 'focus', function (e) {
const focused = focusManager.focusableParent(e.target);
if (focused) {
scrollerInstance.toCenter(focused);
}
};
ScrollerPrototype.toStart = function (elem, immediate) {
if (this.scroller) {
this.scroller.toStart(elem, immediate);
}
};
ScrollerPrototype.toCenter = function (elem, immediate) {
if (this.scroller) {
this.scroller.toCenter(elem, immediate);
}
};
ScrollerPrototype.scrollToPosition = function (pos, immediate) {
if (this.scroller) {
this.scroller.slideTo(pos, immediate);
}
};
ScrollerPrototype.getScrollPosition = function () {
if (this.scroller) {
return this.scroller.getScrollPosition();
}
};
ScrollerPrototype.getScrollSize = function () {
if (this.scroller) {
return this.scroller.getScrollSize();
}
};
ScrollerPrototype.getScrollEventName = function () {
if (this.scroller) {
return this.scroller.getScrollEventName();
}
};
ScrollerPrototype.getScrollSlider = function () {
if (this.scroller) {
return this.scroller.getScrollSlider();
}
};
ScrollerPrototype.addScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.addEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
ScrollerPrototype.removeScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.removeEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
function onInputCommand(e) {
const cmd = e.detail.command;
if (cmd === 'end') {
focusManager.focusLast(this, '.' + this.getAttribute('data-navcommands'));
e.preventDefault();
e.stopPropagation();
} else if (cmd === 'pageup') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), -12);
e.preventDefault();
e.stopPropagation();
} else if (cmd === 'pagedown') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), 12);
e.preventDefault();
e.stopPropagation();
}
}
ScrollerPrototype.attachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.on(this, onInputCommand);
}
const horizontal = this.getAttribute('data-horizontal') !== 'false';
const slider = this.querySelector('.scrollSlider');
if (horizontal) {
slider.style['white-space'] = 'nowrap';
}
const scrollFrame = this;
const enableScrollButtons = layoutManager.desktop && horizontal && this.getAttribute('data-scrollbuttons') !== 'false';
const options = {
horizontal: horizontal,
mouseDragging: 1,
mouseWheel: this.getAttribute('data-mousewheel') !== 'false',
touchDragging: 1,
slidee: slider,
scrollBy: 200,
speed: horizontal ? 270 : 240,
elasticBounds: 1,
dragHandle: 1,
autoImmediate: true,
skipSlideToWhenVisible: this.getAttribute('data-skipfocuswhenvisible') === 'true',
dispatchScrollEvent: enableScrollButtons || this.getAttribute('data-scrollevent') === 'true',
hideScrollbar: enableScrollButtons || this.getAttribute('data-hidescrollbar') === 'true',
allowNativeSmoothScroll: this.getAttribute('data-allownativesmoothscroll') === 'true' && !enableScrollButtons,
allowNativeScroll: !enableScrollButtons,
forceHideScrollbars: enableScrollButtons,
// In edge, with the native scroll, the content jumps around when hovering over the buttons
requireAnimation: enableScrollButtons && browser.edge
};
// If just inserted it might not have any height yet - yes this is a hack
this.scroller = new scroller(scrollFrame, options);
this.scroller.init();
this.scroller.reload();
if (layoutManager.tv && this.getAttribute('data-centerfocus')) {
initCenterFocus(this, this.scroller);
}
if (enableScrollButtons) {
loadScrollButtons(this);
}
};
function loadScrollButtons(buttonsScroller) {
import('../emby-scrollbuttons/emby-scrollbuttons').then(() => {
buttonsScroller.insertAdjacentHTML('beforebegin', '<div is="emby-scrollbuttons" class="emby-scrollbuttons padded-right"></div>');
});
}
ScrollerPrototype.pause = function () {
const headroom = this.headroom;
if (headroom) {
headroom.pause();
}
};
ScrollerPrototype.resume = function () {
const headroom = this.headroom;
if (headroom) {
headroom.resume();
}
};
ScrollerPrototype.detachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.off(this, onInputCommand);
}
const headroom = this.headroom;
if (headroom) {
headroom.destroy();
this.headroom = null;
}
const scrollerInstance = this.scroller;
if (scrollerInstance) {
scrollerInstance.destroy();
this.scroller = null;
}
};
document.registerElement('emby-scroller', {
prototype: ScrollerPrototype,
extends: 'div'
}, {
capture: true,
passive: true
});
}
ScrollerPrototype.scrollToBeginning = function () {
if (this.scroller) {
this.scroller.slideTo(0, true);
}
};
ScrollerPrototype.toStart = function (elem, immediate) {
if (this.scroller) {
this.scroller.toStart(elem, immediate);
}
};
ScrollerPrototype.toCenter = function (elem, immediate) {
if (this.scroller) {
this.scroller.toCenter(elem, immediate);
}
};
ScrollerPrototype.scrollToPosition = function (pos, immediate) {
if (this.scroller) {
this.scroller.slideTo(pos, immediate);
}
};
ScrollerPrototype.getScrollPosition = function () {
if (this.scroller) {
return this.scroller.getScrollPosition();
}
};
ScrollerPrototype.getScrollSize = function () {
if (this.scroller) {
return this.scroller.getScrollSize();
}
};
ScrollerPrototype.getScrollEventName = function () {
if (this.scroller) {
return this.scroller.getScrollEventName();
}
};
ScrollerPrototype.getScrollSlider = function () {
if (this.scroller) {
return this.scroller.getScrollSlider();
}
};
ScrollerPrototype.addScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.addEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
ScrollerPrototype.removeScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.removeEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
function onInputCommand(e) {
const cmd = e.detail.command;
if (cmd === 'end') {
focusManager.focusLast(this, '.' + this.getAttribute('data-navcommands'));
e.preventDefault();
e.stopPropagation();
} else if (cmd === 'pageup') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), -12);
e.preventDefault();
e.stopPropagation();
} else if (cmd === 'pagedown') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), 12);
e.preventDefault();
e.stopPropagation();
}
}
ScrollerPrototype.attachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.on(this, onInputCommand);
}
const horizontal = this.getAttribute('data-horizontal') !== 'false';
const slider = this.querySelector('.scrollSlider');
if (horizontal) {
slider.style['white-space'] = 'nowrap';
}
const scrollFrame = this;
const enableScrollButtons = layoutManager.desktop && horizontal && this.getAttribute('data-scrollbuttons') !== 'false';
const options = {
horizontal: horizontal,
mouseDragging: 1,
mouseWheel: this.getAttribute('data-mousewheel') !== 'false',
touchDragging: 1,
slidee: slider,
scrollBy: 200,
speed: horizontal ? 270 : 240,
elasticBounds: 1,
dragHandle: 1,
autoImmediate: true,
skipSlideToWhenVisible: this.getAttribute('data-skipfocuswhenvisible') === 'true',
dispatchScrollEvent: enableScrollButtons || this.getAttribute('data-scrollevent') === 'true',
hideScrollbar: enableScrollButtons || this.getAttribute('data-hidescrollbar') === 'true',
allowNativeSmoothScroll: this.getAttribute('data-allownativesmoothscroll') === 'true' && !enableScrollButtons,
allowNativeScroll: !enableScrollButtons,
forceHideScrollbars: enableScrollButtons,
// In edge, with the native scroll, the content jumps around when hovering over the buttons
requireAnimation: enableScrollButtons && browser.edge
};
// If just inserted it might not have any height yet - yes this is a hack
this.scroller = new scroller(scrollFrame, options);
this.scroller.init();
this.scroller.reload();
if (layoutManager.tv && this.getAttribute('data-centerfocus')) {
initCenterFocus(this, this.scroller);
}
if (enableScrollButtons) {
loadScrollButtons(this);
}
};
function loadScrollButtons(buttonsScroller) {
import('../emby-scrollbuttons/emby-scrollbuttons').then(() => {
buttonsScroller.insertAdjacentHTML('beforebegin', '<div is="emby-scrollbuttons" class="emby-scrollbuttons padded-right"></div>');
});
}
ScrollerPrototype.pause = function () {
const headroom = this.headroom;
if (headroom) {
headroom.pause();
}
};
ScrollerPrototype.resume = function () {
const headroom = this.headroom;
if (headroom) {
headroom.resume();
}
};
ScrollerPrototype.detachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.off(this, onInputCommand);
}
const headroom = this.headroom;
if (headroom) {
headroom.destroy();
this.headroom = null;
}
const scrollerInstance = this.scroller;
if (scrollerInstance) {
scrollerInstance.destroy();
this.scroller = null;
}
};
document.registerElement('emby-scroller', {
prototype: ScrollerPrototype,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -4,152 +4,149 @@ import actionsheet from '../../components/actionSheet/actionSheet';
import './emby-select.scss';
import 'webcomponents.js/webcomponents-lite';
/* eslint-disable indent */
const EmbySelectPrototype = Object.create(HTMLSelectElement.prototype);
const EmbySelectPrototype = Object.create(HTMLSelectElement.prototype);
function enableNativeMenu() {
if (browser.edgeUwp || browser.xboxOne) {
return true;
}
// Doesn't seem to work at all
if (browser.tizen || browser.orsay || browser.web0s) {
return false;
}
// Take advantage of the native input methods
if (browser.tv) {
return true;
}
return !layoutManager.tv;
function enableNativeMenu() {
if (browser.edgeUwp || browser.xboxOne) {
return true;
}
function triggerChange(select) {
const evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
select.dispatchEvent(evt);
// Doesn't seem to work at all
if (browser.tizen || browser.orsay || browser.web0s) {
return false;
}
function setValue(select, value) {
select.value = value;
// Take advantage of the native input methods
if (browser.tv) {
return true;
}
function showActionSheet(select) {
const labelElem = getLabel(select);
const title = labelElem ? (labelElem.textContent || labelElem.innerText) : null;
return !layoutManager.tv;
}
actionsheet.show({
items: select.options,
positionTo: select,
title: title
function triggerChange(select) {
const evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
select.dispatchEvent(evt);
}
}).then(function (value) {
setValue(select, value);
triggerChange(select);
});
}
function setValue(select, value) {
select.value = value;
}
function getLabel(select) {
let elem = select.previousSibling;
while (elem && elem.tagName !== 'LABEL') {
elem = elem.previousSibling;
}
return elem;
}
function showActionSheet(select) {
const labelElem = getLabel(select);
const title = labelElem ? (labelElem.textContent || labelElem.innerText) : null;
function onFocus() {
const label = getLabel(this);
if (label) {
label.classList.add('selectLabelFocused');
}
}
actionsheet.show({
items: select.options,
positionTo: select,
title: title
function onBlur() {
const label = getLabel(this);
if (label) {
label.classList.remove('selectLabelFocused');
}
}
function onMouseDown(e) {
// e.button=0 for primary (left) mouse button click
if (!e.button && !enableNativeMenu()) {
e.preventDefault();
showActionSheet(this);
}
}
function onKeyDown(e) {
switch (e.keyCode) {
case 13:
if (!enableNativeMenu()) {
e.preventDefault();
showActionSheet(this);
}
return;
case 37:
case 38:
case 39:
case 40:
if (layoutManager.tv) {
e.preventDefault();
}
return;
default:
break;
}
}
let inputId = 0;
EmbySelectPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embyselect' + inputId;
inputId++;
}
this.classList.add('emby-select-withcolor');
if (layoutManager.tv) {
this.classList.add('emby-select-focusscale');
}
this.addEventListener('mousedown', onMouseDown);
this.addEventListener('keydown', onKeyDown);
this.addEventListener('focus', onFocus);
this.addEventListener('blur', onBlur);
};
EmbySelectPrototype.attachedCallback = function () {
if (this.classList.contains('emby-select')) {
return;
}
this.classList.add('emby-select');
const label = this.ownerDocument.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('selectLabel');
label.htmlFor = this.id;
this.parentNode?.insertBefore(label, this);
if (this.classList.contains('emby-select-withcolor')) {
this.parentNode?.insertAdjacentHTML('beforeend', '<div class="selectArrowContainer"><div style="visibility:hidden;display:none;">0</div><span class="selectArrow material-icons keyboard_arrow_down" aria-hidden="true"></span></div>');
}
};
EmbySelectPrototype.setLabel = function (text) {
const label = this.parentNode?.querySelector('label');
label.innerText = text;
};
document.registerElement('emby-select', {
prototype: EmbySelectPrototype,
extends: 'select'
}).then(function (value) {
setValue(select, value);
triggerChange(select);
});
}
function getLabel(select) {
let elem = select.previousSibling;
while (elem && elem.tagName !== 'LABEL') {
elem = elem.previousSibling;
}
return elem;
}
function onFocus() {
const label = getLabel(this);
if (label) {
label.classList.add('selectLabelFocused');
}
}
function onBlur() {
const label = getLabel(this);
if (label) {
label.classList.remove('selectLabelFocused');
}
}
function onMouseDown(e) {
// e.button=0 for primary (left) mouse button click
if (!e.button && !enableNativeMenu()) {
e.preventDefault();
showActionSheet(this);
}
}
function onKeyDown(e) {
switch (e.keyCode) {
case 13:
if (!enableNativeMenu()) {
e.preventDefault();
showActionSheet(this);
}
return;
case 37:
case 38:
case 39:
case 40:
if (layoutManager.tv) {
e.preventDefault();
}
return;
default:
break;
}
}
let inputId = 0;
EmbySelectPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embyselect' + inputId;
inputId++;
}
this.classList.add('emby-select-withcolor');
if (layoutManager.tv) {
this.classList.add('emby-select-focusscale');
}
this.addEventListener('mousedown', onMouseDown);
this.addEventListener('keydown', onKeyDown);
this.addEventListener('focus', onFocus);
this.addEventListener('blur', onBlur);
};
EmbySelectPrototype.attachedCallback = function () {
if (this.classList.contains('emby-select')) {
return;
}
this.classList.add('emby-select');
const label = this.ownerDocument.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('selectLabel');
label.htmlFor = this.id;
this.parentNode?.insertBefore(label, this);
if (this.classList.contains('emby-select-withcolor')) {
this.parentNode?.insertAdjacentHTML('beforeend', '<div class="selectArrowContainer"><div style="visibility:hidden;display:none;">0</div><span class="selectArrow material-icons keyboard_arrow_down" aria-hidden="true"></span></div>');
}
};
EmbySelectPrototype.setLabel = function (text) {
const label = this.parentNode?.querySelector('label');
label.innerText = text;
};
document.registerElement('emby-select', {
prototype: EmbySelectPrototype,
extends: 'select'
});
/* eslint-enable indent */

File diff suppressed because it is too large Load diff

View file

@ -7,334 +7,332 @@ import layoutManager from '../../components/layoutManager';
import './emby-tabs.scss';
import '../../styles/scrollstyles.scss';
/* eslint-disable indent */
const EmbyTabs = Object.create(HTMLDivElement.prototype);
const buttonClass = 'emby-tab-button';
const activeButtonClass = buttonClass + '-active';
const EmbyTabs = Object.create(HTMLDivElement.prototype);
const buttonClass = 'emby-tab-button';
const activeButtonClass = buttonClass + '-active';
function setActiveTabButton(newButton) {
newButton.classList.add(activeButtonClass);
function setActiveTabButton(newButton) {
newButton.classList.add(activeButtonClass);
}
function getTabPanel() {
return null;
}
function removeActivePanelClass() {
const tabPanel = getTabPanel();
if (tabPanel) {
tabPanel.classList.remove('is-active');
}
}
function fadeInRight(elem) {
const pct = browser.mobile ? '4%' : '0.5%';
const keyframes = [
{ opacity: '0', transform: 'translate3d(' + pct + ', 0, 0)', offset: 0 },
{ opacity: '1', transform: 'none', offset: 1 }];
elem.animate(keyframes, {
duration: 160,
iterations: 1,
easing: 'ease-out'
});
}
function triggerBeforeTabChange(tabs, index, previousIndex) {
tabs.dispatchEvent(new CustomEvent('beforetabchange', {
detail: {
selectedTabIndex: index,
previousIndex: previousIndex
}
}));
if (previousIndex != null && previousIndex !== index) {
removeActivePanelClass();
}
function getTabPanel() {
return null;
const newPanel = getTabPanel();
if (newPanel) {
// animate new panel ?
if (newPanel.animate) {
fadeInRight(newPanel);
}
newPanel.classList.add('is-active');
}
}
function removeActivePanelClass() {
const tabPanel = getTabPanel();
if (tabPanel) {
tabPanel.classList.remove('is-active');
}
}
function onClick(e) {
const tabs = this;
function fadeInRight(elem) {
const pct = browser.mobile ? '4%' : '0.5%';
const current = tabs.querySelector('.' + activeButtonClass);
const tabButton = dom.parentWithClass(e.target, buttonClass);
const keyframes = [
{ opacity: '0', transform: 'translate3d(' + pct + ', 0, 0)', offset: 0 },
{ opacity: '1', transform: 'none', offset: 1 }];
elem.animate(keyframes, {
duration: 160,
iterations: 1,
easing: 'ease-out'
});
}
function triggerBeforeTabChange(tabs, index, previousIndex) {
tabs.dispatchEvent(new CustomEvent('beforetabchange', {
detail: {
selectedTabIndex: index,
previousIndex: previousIndex
}
}));
if (previousIndex != null && previousIndex !== index) {
removeActivePanelClass();
if (tabButton && tabButton !== current) {
if (current) {
current.classList.remove(activeButtonClass);
}
const newPanel = getTabPanel();
const previousIndex = current ? parseInt(current.getAttribute('data-index'), 10) : null;
if (newPanel) {
// animate new panel ?
if (newPanel.animate) {
fadeInRight(newPanel);
}
setActiveTabButton(tabButton);
newPanel.classList.add('is-active');
}
}
const index = parseInt(tabButton.getAttribute('data-index'), 10);
function onClick(e) {
const tabs = this;
triggerBeforeTabChange(tabs, index, previousIndex);
const current = tabs.querySelector('.' + activeButtonClass);
const tabButton = dom.parentWithClass(e.target, buttonClass);
if (tabButton && tabButton !== current) {
if (current) {
current.classList.remove(activeButtonClass);
}
const previousIndex = current ? parseInt(current.getAttribute('data-index'), 10) : null;
setActiveTabButton(tabButton);
const index = parseInt(tabButton.getAttribute('data-index'), 10);
triggerBeforeTabChange(tabs, index, previousIndex);
// If toCenter is called syncronously within the click event, it sometimes ends up canceling it
setTimeout(function () {
tabs.selectedTabIndex = index;
tabs.dispatchEvent(new CustomEvent('tabchange', {
detail: {
selectedTabIndex: index,
previousIndex: previousIndex
}
}));
}, 120);
if (tabs.scroller) {
tabs.scroller.toCenter(tabButton, false);
}
}
}
function onFocusIn(e) {
const tabs = this;
const tabButton = dom.parentWithClass(e.target, buttonClass);
if (tabButton && tabs.scroller) {
tabs.scroller.toCenter(tabButton, false);
}
}
function onFocusOut(e) {
const parentContainer = e.target.parentNode;
const previousFocus = parentContainer.querySelector('.lastFocused');
if (previousFocus) {
previousFocus.classList.remove('lastFocused');
}
e.target.classList.add('lastFocused');
}
function initScroller(tabs) {
if (tabs.scroller) {
return;
}
const contentScrollSlider = tabs.querySelector('.emby-tabs-slider');
if (contentScrollSlider) {
tabs.scroller = new scroller(tabs, {
horizontal: 1,
itemNav: 0,
mouseDragging: 1,
touchDragging: 1,
slidee: contentScrollSlider,
smart: true,
releaseSwing: true,
scrollBy: 200,
speed: 120,
elasticBounds: 1,
dragHandle: 1,
dynamicHandle: 1,
clickBar: 1,
hiddenScroll: true,
// In safari the transform is causing the headers to occasionally disappear or flicker
requireAnimation: !browser.safari,
allowNativeSmoothScroll: true
});
tabs.scroller.init();
} else {
tabs.classList.add('scrollX');
tabs.classList.add('hiddenScrollX');
tabs.classList.add('smoothScrollX');
}
}
EmbyTabs.createdCallback = function () {
if (this.classList.contains('emby-tabs')) {
return;
}
this.classList.add('emby-tabs');
this.classList.add('focusable');
dom.addEventListener(this, 'click', onClick, {
passive: true
});
if (layoutManager.tv) {
dom.addEventListener(this, 'focusin', onFocusIn, { passive: true });
}
dom.addEventListener(this, 'focusout', onFocusOut);
};
EmbyTabs.focus = function () {
const selectedTab = this.querySelector('.' + activeButtonClass);
const lastFocused = this.querySelector('.lastFocused');
if (lastFocused) {
focusManager.focus(lastFocused);
} else if (selectedTab) {
focusManager.focus(selectedTab);
} else {
focusManager.autoFocus(this);
}
};
EmbyTabs.refresh = function () {
if (this.scroller) {
this.scroller.reload();
}
};
EmbyTabs.attachedCallback = function () {
initScroller(this);
const current = this.querySelector('.' + activeButtonClass);
const currentIndex = current ? parseInt(current.getAttribute('data-index'), 10) : parseInt(this.getAttribute('data-index') || '0', 10);
if (currentIndex !== -1) {
this.selectedTabIndex = currentIndex;
const tabButtons = this.querySelectorAll('.' + buttonClass);
const newTabButton = tabButtons[currentIndex];
if (newTabButton) {
setActiveTabButton(newTabButton);
}
}
if (!this.readyFired) {
this.readyFired = true;
this.dispatchEvent(new CustomEvent('ready', {}));
}
};
EmbyTabs.detachedCallback = function () {
if (this.scroller) {
this.scroller.destroy();
this.scroller = null;
}
dom.removeEventListener(this, 'click', onClick, {
passive: true
});
if (layoutManager.tv) {
dom.removeEventListener(this, 'focusin', onFocusIn, { passive: true });
}
};
function getSelectedTabButton(elem) {
return elem.querySelector('.' + activeButtonClass);
}
EmbyTabs.selectedIndex = function (selected, triggerEvent) {
const tabs = this;
if (selected == null) {
return tabs.selectedTabIndex || 0;
}
const current = tabs.selectedIndex();
tabs.selectedTabIndex = selected;
const tabButtons = tabs.querySelectorAll('.' + buttonClass);
if (current === selected || triggerEvent === false) {
triggerBeforeTabChange(tabs, selected, current);
// If toCenter is called syncronously within the click event, it sometimes ends up canceling it
setTimeout(function () {
tabs.selectedTabIndex = index;
tabs.dispatchEvent(new CustomEvent('tabchange', {
detail: {
selectedTabIndex: selected
selectedTabIndex: index,
previousIndex: previousIndex
}
}));
}, 120);
const currentTabButton = tabButtons[current];
setActiveTabButton(tabButtons[selected]);
if (current !== selected && currentTabButton) {
currentTabButton.classList.remove(activeButtonClass);
}
} else {
onClick.call(tabs, {
target: tabButtons[selected]
});
if (tabs.scroller) {
tabs.scroller.toCenter(tabButton, false);
}
};
}
}
function getSibling(elem, method) {
let sibling = elem[method];
function onFocusIn(e) {
const tabs = this;
const tabButton = dom.parentWithClass(e.target, buttonClass);
if (tabButton && tabs.scroller) {
tabs.scroller.toCenter(tabButton, false);
}
}
while (sibling) {
if (sibling.classList.contains(buttonClass) && !sibling.classList.contains('hide')) {
return sibling;
}
function onFocusOut(e) {
const parentContainer = e.target.parentNode;
const previousFocus = parentContainer.querySelector('.lastFocused');
if (previousFocus) {
previousFocus.classList.remove('lastFocused');
}
e.target.classList.add('lastFocused');
}
sibling = sibling[method];
}
return null;
function initScroller(tabs) {
if (tabs.scroller) {
return;
}
EmbyTabs.selectNext = function () {
const current = getSelectedTabButton(this);
const contentScrollSlider = tabs.querySelector('.emby-tabs-slider');
if (contentScrollSlider) {
tabs.scroller = new scroller(tabs, {
horizontal: 1,
itemNav: 0,
mouseDragging: 1,
touchDragging: 1,
slidee: contentScrollSlider,
smart: true,
releaseSwing: true,
scrollBy: 200,
speed: 120,
elasticBounds: 1,
dragHandle: 1,
dynamicHandle: 1,
clickBar: 1,
hiddenScroll: true,
const sibling = getSibling(current, 'nextSibling');
// In safari the transform is causing the headers to occasionally disappear or flicker
requireAnimation: !browser.safari,
allowNativeSmoothScroll: true
});
tabs.scroller.init();
} else {
tabs.classList.add('scrollX');
tabs.classList.add('hiddenScrollX');
tabs.classList.add('smoothScrollX');
}
}
if (sibling) {
onClick.call(this, {
target: sibling
});
EmbyTabs.createdCallback = function () {
if (this.classList.contains('emby-tabs')) {
return;
}
this.classList.add('emby-tabs');
this.classList.add('focusable');
dom.addEventListener(this, 'click', onClick, {
passive: true
});
if (layoutManager.tv) {
dom.addEventListener(this, 'focusin', onFocusIn, { passive: true });
}
dom.addEventListener(this, 'focusout', onFocusOut);
};
EmbyTabs.focus = function () {
const selectedTab = this.querySelector('.' + activeButtonClass);
const lastFocused = this.querySelector('.lastFocused');
if (lastFocused) {
focusManager.focus(lastFocused);
} else if (selectedTab) {
focusManager.focus(selectedTab);
} else {
focusManager.autoFocus(this);
}
};
EmbyTabs.refresh = function () {
if (this.scroller) {
this.scroller.reload();
}
};
EmbyTabs.attachedCallback = function () {
initScroller(this);
const current = this.querySelector('.' + activeButtonClass);
const currentIndex = current ? parseInt(current.getAttribute('data-index'), 10) : parseInt(this.getAttribute('data-index') || '0', 10);
if (currentIndex !== -1) {
this.selectedTabIndex = currentIndex;
const tabButtons = this.querySelectorAll('.' + buttonClass);
const newTabButton = tabButtons[currentIndex];
if (newTabButton) {
setActiveTabButton(newTabButton);
}
};
}
EmbyTabs.selectPrevious = function () {
const current = getSelectedTabButton(this);
if (!this.readyFired) {
this.readyFired = true;
this.dispatchEvent(new CustomEvent('ready', {}));
}
};
const sibling = getSibling(current, 'previousSibling');
EmbyTabs.detachedCallback = function () {
if (this.scroller) {
this.scroller.destroy();
this.scroller = null;
}
if (sibling) {
onClick.call(this, {
target: sibling
});
}
};
dom.removeEventListener(this, 'click', onClick, {
passive: true
});
EmbyTabs.triggerBeforeTabChange = function () {
const tabs = this;
if (layoutManager.tv) {
dom.removeEventListener(this, 'focusin', onFocusIn, { passive: true });
}
};
triggerBeforeTabChange(tabs, tabs.selectedIndex());
};
function getSelectedTabButton(elem) {
return elem.querySelector('.' + activeButtonClass);
}
EmbyTabs.triggerTabChange = function () {
const tabs = this;
EmbyTabs.selectedIndex = function (selected, triggerEvent) {
const tabs = this;
if (selected == null) {
return tabs.selectedTabIndex || 0;
}
const current = tabs.selectedIndex();
tabs.selectedTabIndex = selected;
const tabButtons = tabs.querySelectorAll('.' + buttonClass);
if (current === selected || triggerEvent === false) {
triggerBeforeTabChange(tabs, selected, current);
tabs.dispatchEvent(new CustomEvent('tabchange', {
detail: {
selectedTabIndex: tabs.selectedIndex()
selectedTabIndex: selected
}
}));
};
EmbyTabs.setTabEnabled = function (index, enabled) {
const btn = this.querySelector('.emby-tab-button[data-index="' + index + '"]');
const currentTabButton = tabButtons[current];
setActiveTabButton(tabButtons[selected]);
if (enabled) {
btn.classList.remove('hide');
} else {
btn.classList.remove('add');
if (current !== selected && currentTabButton) {
currentTabButton.classList.remove(activeButtonClass);
}
};
} else {
onClick.call(tabs, {
target: tabButtons[selected]
});
}
};
document.registerElement('emby-tabs', {
prototype: EmbyTabs,
extends: 'div'
});
function getSibling(elem, method) {
let sibling = elem[method];
while (sibling) {
if (sibling.classList.contains(buttonClass) && !sibling.classList.contains('hide')) {
return sibling;
}
sibling = sibling[method];
}
return null;
}
EmbyTabs.selectNext = function () {
const current = getSelectedTabButton(this);
const sibling = getSibling(current, 'nextSibling');
if (sibling) {
onClick.call(this, {
target: sibling
});
}
};
EmbyTabs.selectPrevious = function () {
const current = getSelectedTabButton(this);
const sibling = getSibling(current, 'previousSibling');
if (sibling) {
onClick.call(this, {
target: sibling
});
}
};
EmbyTabs.triggerBeforeTabChange = function () {
const tabs = this;
triggerBeforeTabChange(tabs, tabs.selectedIndex());
};
EmbyTabs.triggerTabChange = function () {
const tabs = this;
tabs.dispatchEvent(new CustomEvent('tabchange', {
detail: {
selectedTabIndex: tabs.selectedIndex()
}
}));
};
EmbyTabs.setTabEnabled = function (index, enabled) {
const btn = this.querySelector('.emby-tab-button[data-index="' + index + '"]');
if (enabled) {
btn.classList.remove('hide');
} else {
btn.classList.remove('add');
}
};
document.registerElement('emby-tabs', {
prototype: EmbyTabs,
extends: 'div'
});
/* eslint-enable indent */

View file

@ -19,119 +19,117 @@ function calculateOffset(textarea) {
return offset;
}
/* eslint-disable indent */
function autoGrow(textarea, maxLines) {
const self = this;
function autoGrow(textarea, maxLines) {
const self = this;
if (maxLines === undefined) {
maxLines = 999;
}
let offset;
function reset() {
textarea.rows = 1;
offset = calculateOffset(textarea);
self.rows = textarea.rows || 1;
self.lineHeight = (textarea.scrollHeight / self.rows) - (offset / self.rows);
self.maxAllowedHeight = (self.lineHeight * maxLines) - offset;
}
function autogrowFn() {
if (!self.lineHeight || self.lineHeight <= 0) {
reset();
}
if (self.lineHeight <= 0) {
textarea.style.overflowY = 'scroll';
textarea.style.height = 'auto';
textarea.rows = 3;
return;
}
let newHeight = 0;
if ((textarea.scrollHeight - offset) > self.maxAllowedHeight) {
textarea.style.overflowY = 'scroll';
newHeight = self.maxAllowedHeight;
} else {
textarea.style.overflowY = 'hidden';
textarea.style.height = 'auto';
newHeight = textarea.scrollHeight/* - offset*/;
}
textarea.style.height = newHeight + 'px';
}
// Call autogrowFn() when textarea's value is changed
textarea.addEventListener('input', autogrowFn);
textarea.addEventListener('focus', autogrowFn);
textarea.addEventListener('valueset', autogrowFn);
autogrowFn();
if (maxLines === undefined) {
maxLines = 999;
}
const EmbyTextAreaPrototype = Object.create(HTMLTextAreaElement.prototype);
let elementId = 0;
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
const descriptor = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
// descriptor returning null in webos
if (descriptor && descriptor.configurable) {
const baseSetMethod = descriptor.set;
descriptor.set = function (value) {
baseSetMethod.call(this, value);
this.dispatchEvent(new CustomEvent('valueset', {
bubbles: false,
cancelable: false
}));
};
Object.defineProperty(HTMLTextAreaElement.prototype, 'value', descriptor);
}
let offset;
function reset() {
textarea.rows = 1;
offset = calculateOffset(textarea);
self.rows = textarea.rows || 1;
self.lineHeight = (textarea.scrollHeight / self.rows) - (offset / self.rows);
self.maxAllowedHeight = (self.lineHeight * maxLines) - offset;
}
EmbyTextAreaPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embytextarea' + elementId;
elementId++;
function autogrowFn() {
if (!self.lineHeight || self.lineHeight <= 0) {
reset();
}
};
EmbyTextAreaPrototype.attachedCallback = function () {
if (this.classList.contains('emby-textarea')) {
if (self.lineHeight <= 0) {
textarea.style.overflowY = 'scroll';
textarea.style.height = 'auto';
textarea.rows = 3;
return;
}
let newHeight = 0;
this.rows = 1;
this.classList.add('emby-textarea');
if ((textarea.scrollHeight - offset) > self.maxAllowedHeight) {
textarea.style.overflowY = 'scroll';
newHeight = self.maxAllowedHeight;
} else {
textarea.style.overflowY = 'hidden';
textarea.style.height = 'auto';
newHeight = textarea.scrollHeight/* - offset*/;
}
textarea.style.height = newHeight + 'px';
}
const parentNode = this.parentNode;
const label = this.ownerDocument.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('textareaLabel');
// Call autogrowFn() when textarea's value is changed
textarea.addEventListener('input', autogrowFn);
textarea.addEventListener('focus', autogrowFn);
textarea.addEventListener('valueset', autogrowFn);
label.htmlFor = this.id;
parentNode.insertBefore(label, this);
autogrowFn();
}
this.addEventListener('focus', function () {
label.classList.add('textareaLabelFocused');
label.classList.remove('textareaLabelUnfocused');
});
this.addEventListener('blur', function () {
label.classList.remove('textareaLabelFocused');
label.classList.add('textareaLabelUnfocused');
});
const EmbyTextAreaPrototype = Object.create(HTMLTextAreaElement.prototype);
this.label = function (text) {
label.innerText = text;
let elementId = 0;
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
const descriptor = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
// descriptor returning null in webos
if (descriptor && descriptor.configurable) {
const baseSetMethod = descriptor.set;
descriptor.set = function (value) {
baseSetMethod.call(this, value);
this.dispatchEvent(new CustomEvent('valueset', {
bubbles: false,
cancelable: false
}));
};
new autoGrow(this);
};
Object.defineProperty(HTMLTextAreaElement.prototype, 'value', descriptor);
}
}
document.registerElement('emby-textarea', {
prototype: EmbyTextAreaPrototype,
extends: 'textarea'
EmbyTextAreaPrototype.createdCallback = function () {
if (!this.id) {
this.id = 'embytextarea' + elementId;
elementId++;
}
};
EmbyTextAreaPrototype.attachedCallback = function () {
if (this.classList.contains('emby-textarea')) {
return;
}
this.rows = 1;
this.classList.add('emby-textarea');
const parentNode = this.parentNode;
const label = this.ownerDocument.createElement('label');
label.innerText = this.getAttribute('label') || '';
label.classList.add('textareaLabel');
label.htmlFor = this.id;
parentNode.insertBefore(label, this);
this.addEventListener('focus', function () {
label.classList.add('textareaLabelFocused');
label.classList.remove('textareaLabelUnfocused');
});
this.addEventListener('blur', function () {
label.classList.remove('textareaLabelFocused');
label.classList.add('textareaLabelUnfocused');
});
/* eslint-enable indent */
this.label = function (text) {
label.innerText = text;
};
new autoGrow(this);
};
document.registerElement('emby-textarea', {
prototype: EmbyTextAreaPrototype,
extends: 'textarea'
});

View file

@ -1,51 +1,48 @@
import './emby-toggle.scss';
import 'webcomponents.js/webcomponents-lite';
/* eslint-disable indent */
const EmbyTogglePrototype = Object.create(HTMLInputElement.prototype);
const EmbyTogglePrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) {
// Don't submit form on enter
if (e.keyCode === 13) {
e.preventDefault();
function onKeyDown(e) {
// Don't submit form on enter
if (e.keyCode === 13) {
e.preventDefault();
this.checked = !this.checked;
this.checked = !this.checked;
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
return false;
}
}
return false;
}
EmbyTogglePrototype.attachedCallback = function () {
if (this.getAttribute('data-embytoggle') === 'true') {
return;
}
EmbyTogglePrototype.attachedCallback = function () {
if (this.getAttribute('data-embytoggle') === 'true') {
return;
}
this.setAttribute('data-embytoggle', 'true');
this.setAttribute('data-embytoggle', 'true');
this.classList.add('mdl-switch__input');
this.classList.add('mdl-switch__input');
const labelElement = this.parentNode;
labelElement.classList.add('mdl-switch');
labelElement.classList.add('mdl-js-switch');
const labelElement = this.parentNode;
labelElement.classList.add('mdl-switch');
labelElement.classList.add('mdl-js-switch');
const labelTextElement = labelElement.querySelector('span');
const labelTextElement = labelElement.querySelector('span');
labelElement.insertAdjacentHTML('beforeend', '<div class="mdl-switch__trackContainer"><div class="mdl-switch__track"></div><div class="mdl-switch__thumb"><span class="mdl-switch__focus-helper"></span></div></div>');
labelElement.insertAdjacentHTML('beforeend', '<div class="mdl-switch__trackContainer"><div class="mdl-switch__track"></div><div class="mdl-switch__thumb"><span class="mdl-switch__focus-helper"></span></div></div>');
labelTextElement.classList.add('toggleButtonLabel');
labelTextElement.classList.add('mdl-switch__label');
labelTextElement.classList.add('toggleButtonLabel');
labelTextElement.classList.add('mdl-switch__label');
this.addEventListener('keydown', onKeyDown);
};
this.addEventListener('keydown', onKeyDown);
};
document.registerElement('emby-toggle', {
prototype: EmbyTogglePrototype,
extends: 'input'
});
document.registerElement('emby-toggle', {
prototype: EmbyTogglePrototype,
extends: 'input'
});
/* eslint-enable indent */