diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index 48f042d729..7c7801b866 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -33,7 +33,7 @@ jobs: - task: NodeTool@0 displayName: 'Install Node' inputs: - versionSpec: '10.x' + versionSpec: '12.x' - task: Cache@2 displayName: 'Check Cache' @@ -82,7 +82,7 @@ jobs: - task: NodeTool@0 displayName: 'Install Node' inputs: - versionSpec: '10.x' + versionSpec: '12.x' - task: Cache@2 displayName: 'Check Cache' diff --git a/.gitignore b/.gitignore index 10b2d24f42..2bb5bc64d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,578 +1,10 @@ +# config +config.json -# Created by https://www.gitignore.io/api/node,rider,macos,linux,windows,visualstudio,visualstudiocode -# Edit at https://www.gitignore.io/?templates=node,rider,macos,linux,windows,visualstudio,visualstudiocode - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Dependency lockfile -package-lock.json - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -### Rider ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/modules.xml -# .idea/*.iml -# .idea/modules - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### VisualStudioCode ### -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -### VisualStudioCode Patch ### -# Ignore all local history of files -.history - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### VisualStudio ### -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ -# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true -**/wwwroot/lib/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- Backup*.rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# End of https://www.gitignore.io/api/node,rider,macos,linux,windows,visualstudio,visualstudiocode - -# dist for webpack output +# npm dist +node_modules + +# ide +.idea +.vscode diff --git a/package.json b/package.json index 2df8c1a637..c0ff158ec9 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "license": "GPL-2.0-or-later", "devDependencies": { "@babel/core": "^7.8.6", - "@babel/polyfill": "^7.8.7", "@babel/plugin-transform-modules-amd": "^7.8.3", + "@babel/polyfill": "^7.8.7", "@babel/preset-env": "^7.8.6", "autoprefixer": "^9.7.4", "babel-loader": "^8.0.6", @@ -18,7 +18,7 @@ "cssnano": "^4.1.10", "del": "^5.1.0", "eslint": "^6.8.0", - "file-loader": "^5.0.2", + "file-loader": "^6.0.0", "gulp": "^4.0.2", "gulp-babel": "^8.0.0", "gulp-cli": "^2.2.0", @@ -32,7 +32,7 @@ "gulp-sass": "^4.0.2", "gulp-sourcemaps": "^2.6.5", "gulp-terser": "^1.2.0", - "html-webpack-plugin": "^3.2.0", + "html-webpack-plugin": "^4.0.2", "lazypipe": "^1.0.2", "node-sass": "^4.13.1", "postcss-loader": "^3.0.0", @@ -59,30 +59,40 @@ "jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto", "jquery": "^3.4.1", "jstree": "^3.3.7", - "libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus", + "libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf", "material-design-icons-iconfont": "^5.0.1", "native-promise-only": "^0.8.0-a", "page": "^1.11.5", "query-string": "^6.11.1", "resize-observer-polyfill": "^1.5.1", - "shaka-player": "^2.5.9", + "shaka-player": "^2.5.10", "sortablejs": "^1.10.2", "swiper": "^5.3.1", "webcomponents.js": "^0.7.24", "whatwg-fetch": "^3.0.0" }, "babel": { - "presets": ["@babel/preset-env"], - "overrides": [{ + "presets": [ + "@babel/preset-env" + ], + "overrides": [ + { "test": [ - "src/components/cardbuilder/cardBuilder.js", - "src/components/filedownloader.js", - "src/components/filesystem.js", - "src/components/input/keyboardnavigation.js", - "src/components/sanatizefilename.js" + "src/components/autoFocuser.js", + "src/components/cardbuilder/cardBuilder.js", + "src/components/dom.js", + "src/components/filedownloader.js", + "src/components/filesystem.js", + "src/components/input/keyboardnavigation.js", + "src/components/sanatizefilename.js", + "src/scripts/settings/webSettings.js", + "src/components/scrollManager.js" ], - "plugins": ["@babel/plugin-transform-modules-amd"] - }] + "plugins": [ + "@babel/plugin-transform-modules-amd" + ] + } + ] }, "browserslist": [ "last 2 Firefox versions", diff --git a/src/components/apphost.js b/src/components/apphost.js index 590b0e842d..b9567ada94 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -1,4 +1,4 @@ -define(["appSettings", "browser", "events", "htmlMediaHelper", "globalize"], function (appSettings, browser, events, htmlMediaHelper, globalize) { +define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings", "globalize"], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) { "use strict"; function getBaseProfileOptions(item) { @@ -276,10 +276,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "globalize"], fun features.push("otherapppromotions"); features.push("displaymode"); features.push("targetblank"); - // allows users to connect to more than one server - //features.push("multiserver"); features.push("screensaver"); + webSettings.enableMultiServer().then(enabled => { + if (enabled) features.push("multiserver") + }) + if (!browser.orsay && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) { features.push("subtitleappearancesettings"); } diff --git a/src/components/autoFocuser.js b/src/components/autoFocuser.js index 6d99009e67..a469eb8854 100644 --- a/src/components/autoFocuser.js +++ b/src/components/autoFocuser.js @@ -1,22 +1,29 @@ -define(["focusManager", "layoutManager"], function (focusManager, layoutManager) { - "use strict"; +/* eslint-disable indent */ + +/** + * Module for performing auto-focus. + * @module components/autoFocuser + */ + +import focusManager from "focusManager"; +import layoutManager from "layoutManager"; /** * Previously selected element. */ - var activeElement; + let activeElement; /** - * Returns true if AutoFocuser is enabled. + * Returns _true_ if AutoFocuser is enabled. */ - function isEnabled() { + export function isEnabled() { return layoutManager.tv; } /** - * Start AutoFocuser + * Start AutoFocuser. */ - function enable() { + export function enable() { if (!isEnabled()) { return; } @@ -28,24 +35,19 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) console.debug("AutoFocuser enabled"); } - /** - * Create an array from some source. - */ - var arrayFrom = Array.prototype.from || function (src) { - return Array.prototype.slice.call(src); - } - /** * Set focus on a suitable element, taking into account the previously selected. + * @param {HTMLElement} [container] - Element to limit scope. + * @returns {HTMLElement} Focused element. */ - function autoFocus(container) { + export function autoFocus(container) { if (!isEnabled()) { - return; + return null; } container = container || document.body; - var candidates = []; + let candidates = []; if (activeElement) { // These elements are recreated @@ -62,10 +64,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) candidates.push(activeElement); } - candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnResume"))); - candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay"))); + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume"))); + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay"))); - var focusedElement; + let focusedElement; candidates.every(function (element) { if (focusManager.isCurrentlyFocusable(element)) { @@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) if (!focusedElement) { // FIXME: Multiple itemsContainers - var itemsContainer = container.querySelector(".itemsContainer"); + const itemsContainer = container.querySelector(".itemsContainer"); if (itemsContainer) { focusedElement = focusManager.autoFocus(itemsContainer); @@ -93,9 +95,8 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) return focusedElement; } - return { + export default { isEnabled: isEnabled, enable: enable, autoFocus: autoFocus }; -}); diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 9d86bc9d7c..1249f802af 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -1853,3 +1853,14 @@ import 'programStyles'; cell.removeAttribute('data-seriestimerid'); } } + +export default { + getCardsHtml: getCardsHtml, + getDefaultBackgroundClass: getDefaultBackgroundClass, + getDefaultText: getDefaultText, + buildCards: buildCards, + onUserDataChanged: onUserDataChanged, + onTimerCreated: onTimerCreated, + onTimerCancelled: onTimerCancelled, + onSeriesTimerCancelled: onSeriesTimerCancelled +}; diff --git a/src/components/channelmapper/channelmapper.js b/src/components/channelmapper/channelmapper.js index 1b536f440b..2ea7a3a13a 100644 --- a/src/components/channelmapper/channelmapper.js +++ b/src/components/channelmapper/channelmapper.js @@ -1,18 +1,7 @@ -define(["dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (dialogHelper, loading, connectionManager, globalize, actionsheet) { +define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) { "use strict"; return function (options) { - function parentWithClass(elem, className) { - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - if (!elem) { - return null; - } - } - - return elem; - } - function mapChannel(button, channelId, providerChannelId) { loading.show(); var providerId = options.providerId; @@ -26,7 +15,7 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee }, dataType: "json" }).then(function (mapping) { - var listItem = parentWithClass(button, "listItem"); + var listItem = dom.parentWithClass(button, "listItem"); button.setAttribute("data-providerid", mapping.ProviderChannelId); listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName); loading.hide(); @@ -34,7 +23,7 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee } function onChannelsElementClick(e) { - var btnMap = parentWithClass(e.target, "btnMap"); + var btnMap = dom.parentWithClass(e.target, "btnMap"); if (btnMap) { var channelId = btnMap.getAttribute("data-id"); diff --git a/src/components/collectioneditor/collectioneditor.js b/src/components/collectioneditor/collectioneditor.js index 79220ac335..49784df498 100644 --- a/src/components/collectioneditor/collectioneditor.js +++ b/src/components/collectioneditor/collectioneditor.js @@ -1,25 +1,12 @@ -define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { +define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dom, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { 'use strict'; var currentServerId; - function parentWithClass(elem, className) { - - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - - if (!elem) { - return null; - } - } - - return elem; - } - function onSubmit(e) { loading.show(); - var panel = parentWithClass(this, 'dialog'); + var panel = dom.parentWithClass(this, 'dialog'); var collectionId = panel.querySelector('#selectCollectionToAddTo').value; diff --git a/src/components/displaysettings/displaysettings.template.html b/src/components/displaysettings/displaysettings.template.html index 16bbf0dd8a..4ef8c8b1ca 100644 --- a/src/components/displaysettings/displaysettings.template.html +++ b/src/components/displaysettings/displaysettings.template.html @@ -63,7 +63,7 @@
'; diff --git a/src/components/metadataeditor/metadataeditor.js b/src/components/metadataeditor/metadataeditor.js index e8736258fa..84b60b32a3 100644 --- a/src/components/metadataeditor/metadataeditor.js +++ b/src/components/metadataeditor/metadataeditor.js @@ -465,7 +465,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi var id = "txt1" + idInfo.Key; var formatString = idInfo.UrlFormatString || ''; - var labelText = globalize.translate('LabelDynamicExternalId').replace('{0}', idInfo.Name); + var fullName = idInfo.Name; + if (idInfo.Type) { + fullName = idInfo.Name + " " + globalize.translate(idInfo.Type); + } + + var labelText = globalize.translate("LabelDynamicExternalId").replace("{0}", fullName); html += '
'; html += '
'; diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index c274b40799..69356a38c9 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -1,24 +1,10 @@ -define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', 'connectionManager', 'userSettings', 'appRouter', 'globalize', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (shell, dialogHelper, loading, layoutManager, playbackManager, connectionManager, userSettings, appRouter, globalize) { +define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', 'connectionManager', 'userSettings', 'appRouter', 'globalize', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (dom, shell, dialogHelper, loading, layoutManager, playbackManager, connectionManager, userSettings, appRouter, globalize) { 'use strict'; var currentServerId; - function parentWithClass(elem, className) { - - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - - if (!elem) { - return null; - } - } - - return elem; - } - function onSubmit(e) { - - var panel = parentWithClass(this, 'dialog'); + var panel = dom.parentWithClass(this, 'dialog'); var playlistId = panel.querySelector('#selectPlaylistToAddTo').value; var apiClient = connectionManager.getApiClient(currentServerId); @@ -35,11 +21,9 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } function createPlaylist(apiClient, dlg) { - loading.show(); var url = apiClient.getUrl("Playlists", { - Name: dlg.querySelector('#txtNewPlaylistName').value, Ids: dlg.querySelector('.fldSelectedItemIds').value || '', userId: apiClient.getCurrentUserId() @@ -50,9 +34,7 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', type: "POST", url: url, dataType: "json" - }).then(function (result) { - loading.hide(); var id = result.Id; @@ -63,16 +45,13 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } function redirectToPlaylist(apiClient, id) { - appRouter.showItem(id, apiClient.serverId()); } function addToPlaylist(apiClient, dlg, id) { - var itemIds = dlg.querySelector('.fldSelectedItemIds').value || ''; if (id === 'queue') { - playbackManager.queue({ serverId: apiClient.serverId(), ids: itemIds.split(',') @@ -85,7 +64,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', loading.show(); var url = apiClient.getUrl("Playlists/" + id + "/Items", { - Ids: itemIds, userId: apiClient.getCurrentUserId() }); @@ -95,7 +73,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', url: url }).then(function () { - loading.hide(); dlg.submitted = true; @@ -108,7 +85,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } function populatePlaylists(editorOptions, panel) { - var select = panel.querySelector('#selectPlaylistToAddTo'); loading.hide(); @@ -116,7 +92,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', panel.querySelector('.newPlaylistInfo').classList.add('hide'); var options = { - Recursive: true, IncludeItemTypes: "Playlist", SortBy: 'SortName', @@ -125,7 +100,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', var apiClient = connectionManager.getApiClient(currentServerId); apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) { - var html = ''; if (editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) { @@ -135,7 +109,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', html += ''; html += result.Items.map(function (i) { - return ''; }); @@ -159,7 +132,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } function getEditorHtml(items) { - var html = ''; html += '
'; @@ -195,7 +167,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } function initEditor(content, options, items) { - content.querySelector('#selectPlaylistToAddTo').addEventListener('change', function () { if (this.value) { content.querySelector('.newPlaylistInfo').classList.add('hide'); @@ -235,7 +206,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } PlaylistEditor.prototype.show = function (options) { - var items = options.items || {}; currentServerId = options.serverId; @@ -272,7 +242,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', initEditor(dlg, options, items); dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); }); @@ -281,7 +250,6 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', } return dialogHelper.open(dlg).then(function () { - if (layoutManager.tv) { centerFocus(dlg.querySelector('.formDialogContent'), false, false); } diff --git a/src/components/refreshdialog/refreshdialog.js b/src/components/refreshdialog/refreshdialog.js index b5730e592a..1e54d98372 100644 --- a/src/components/refreshdialog/refreshdialog.js +++ b/src/components/refreshdialog/refreshdialog.js @@ -1,19 +1,6 @@ -define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (shell, dialogHelper, loading, layoutManager, connectionManager, appRouter, globalize) { +define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (dom, shell, dialogHelper, loading, layoutManager, connectionManager, appRouter, globalize) { 'use strict'; - function parentWithClass(elem, className) { - - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - - if (!elem) { - return null; - } - } - - return elem; - } - function getEditorHtml() { var html = ''; @@ -65,7 +52,7 @@ define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager' loading.show(); var instance = this; - var dlg = parentWithClass(e.target, 'dialog'); + var dlg = dom.parentWithClass(e.target, 'dialog'); var options = instance.options; var apiClient = connectionManager.getApiClient(options.serverId); diff --git a/src/components/scrollManager.js b/src/components/scrollManager.js index 5fc3729bac..037ca5b059 100644 --- a/src/components/scrollManager.js +++ b/src/components/scrollManager.js @@ -1,38 +1,46 @@ -define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManager) { - "use strict"; +/* eslint-disable indent */ + +/** + * Module for controlling scroll behavior. + * @module components/scrollManager + */ + +import dom from "dom"; +import browser from "browser"; +import layoutManager from "layoutManager"; /** * Scroll time in ms. */ - var ScrollTime = 270; + const ScrollTime = 270; /** * Epsilon for comparing values. */ - var Epsilon = 1e-6; + const Epsilon = 1e-6; // FIXME: Need to scroll to top of page to fully show the top menu. This can be solved by some marker of top most elements or their containers /** * Returns minimum vertical scroll. * Scroll less than that value will be zeroed. * - * @return {number} minimum vertical scroll + * @return {number} Minimum vertical scroll. */ function minimumScrollY() { - var topMenu = document.querySelector(".headerTop"); + const topMenu = document.querySelector(".headerTop"); if (topMenu) { return topMenu.clientHeight; } return 0; } - var supportsSmoothScroll = "scrollBehavior" in document.documentElement.style; + const supportsSmoothScroll = "scrollBehavior" in document.documentElement.style; - var supportsScrollToOptions = false; + let supportsScrollToOptions = false; try { - var elem = document.createElement("div"); + const elem = document.createElement("div"); - var opts = Object.defineProperty({}, "behavior", { + const opts = Object.defineProperty({}, "behavior", { // eslint-disable-next-line getter-return get: function () { supportsScrollToOptions = true; @@ -47,10 +55,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns value clamped by range [min, max]. * - * @param {number} value clamped value - * @param {number} min begining of range - * @param {number} max ending of range - * @return {number} clamped value + * @param {number} value - Clamped value. + * @param {number} min - Begining of range. + * @param {number} max - Ending of range. + * @return {number} Clamped value. */ function clamp(value, min, max) { return value <= min ? min : value >= max ? max : value; @@ -60,15 +68,15 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage * Returns the required delta to fit range 1 into range 2. * In case of range 1 is bigger than range 2 returns delta to fit most out of range part. * - * @param {number} begin1 begining of range 1 - * @param {number} end1 ending of range 1 - * @param {number} begin2 begining of range 2 - * @param {number} end2 ending of range 2 - * @return {number} delta: <0 move range1 to the left, >0 - to the right + * @param {number} begin1 - Begining of range 1. + * @param {number} end1 - Ending of range 1. + * @param {number} begin2 - Begining of range 2. + * @param {number} end2 - Ending of range 2. + * @return {number} Delta: <0 move range1 to the left, >0 - to the right. */ function fitRange(begin1, end1, begin2, end2) { - var delta1 = begin1 - begin2; - var delta2 = end2 - end1; + const delta1 = begin1 - begin2; + const delta2 = end2 - end1; if (delta1 < 0 && delta1 < delta2) { return -delta1; } else if (delta2 < 0) { @@ -80,13 +88,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Ease value. * - * @param {number} t value in range [0, 1] - * @return {number} eased value in range [0, 1] + * @param {number} t - Value in range [0, 1]. + * @return {number} Eased value in range [0, 1]. */ function ease(t) { return t*(2 - t); // easeOutQuad === ease-out } + /** + * @typedef {Object} Rect + * @property {number} left - X coordinate of top-left corner. + * @property {number} top - Y coordinate of top-left corner. + * @property {number} width - Width. + * @property {number} height - Height. + */ + /** * Document scroll wrapper helps to unify scrolling and fix issues of some browsers. * @@ -100,41 +116,68 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage * * Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement */ - function DocumentScroller() { - } - - DocumentScroller.prototype = { + class DocumentScroller { + /** + * Horizontal scroll position. + * @type {number} + */ get scrollLeft() { return window.pageXOffset; - }, + } + set scrollLeft(val) { window.scroll(val, window.pageYOffset); - }, + } + /** + * Vertical scroll position. + * @type {number} + */ get scrollTop() { return window.pageYOffset; - }, + } + set scrollTop(val) { window.scroll(window.pageXOffset, val); - }, + } + /** + * Horizontal scroll size (scroll width). + * @type {number} + */ get scrollWidth() { return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); - }, + } + /** + * Vertical scroll size (scroll height). + * @type {number} + */ get scrollHeight() { return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); - }, + } + /** + * Horizontal client size (client width). + * @type {number} + */ get clientWidth() { return Math.min(document.documentElement.clientWidth, document.body.clientWidth); - }, + } + /** + * Vertical client size (client height). + * @type {number} + */ get clientHeight() { return Math.min(document.documentElement.clientHeight, document.body.clientHeight); - }, + } - getBoundingClientRect: function() { + /** + * Returns bounding client rect. + * @return {Rect} Bounding client rect. + */ + getBoundingClientRect() { // Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport return { left: 0, @@ -142,26 +185,34 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage width: this.clientWidth, height: this.clientHeight }; - }, + } - scrollTo: function() { + /** + * Scrolls window. + * @param {...mixed} args See window.scrollTo. + */ + scrollTo() { window.scrollTo.apply(window, arguments); } - }; - - var documentScroller = new DocumentScroller(); + } /** - * Returns parent element that can be scrolled. If no such, returns documentElement. + * Default (document) scroller. + */ + const documentScroller = new DocumentScroller(); + + /** + * Returns parent element that can be scrolled. If no such, returns document scroller. * - * @param {HTMLElement} element element for which parent is being searched - * @param {boolean} vertical search for vertical scrollable parent + * @param {HTMLElement} element - Element for which parent is being searched. + * @param {boolean} vertical - Search for vertical scrollable parent. + * @param {HTMLElement|DocumentScroller} Parent element that can be scrolled or document scroller. */ function getScrollableParent(element, vertical) { if (element) { - var nameScroll = "scrollWidth"; - var nameClient = "clientWidth"; - var nameClass = "scrollX"; + let nameScroll = "scrollWidth"; + let nameClient = "clientWidth"; + let nameClass = "scrollX"; if (vertical) { nameScroll = "scrollHeight"; @@ -169,7 +220,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage nameClass = "scrollY"; } - var parent = element.parentElement; + let parent = element.parentElement; while (parent) { // Skip 'emby-scroller' because it scrolls by itself @@ -187,20 +238,20 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * @typedef {Object} ScrollerData - * @property {number} scrollPos current scroll position - * @property {number} scrollSize scroll size - * @property {number} clientSize client size + * @property {number} scrollPos - Current scroll position. + * @property {number} scrollSize - Scroll size. + * @property {number} clientSize - Client size. */ /** - * Returns scroll data for specified orientation. + * Returns scroller data for specified orientation. * - * @param {HTMLElement} scroller scroller - * @param {boolean} vertical vertical scroll data - * @return {ScrollerData} scroll data + * @param {HTMLElement} scroller - Scroller. + * @param {boolean} vertical - Vertical scroller data. + * @return {ScrollerData} Scroller data. */ function getScrollerData(scroller, vertical) { - var data = {}; + let data = {}; if (!vertical) { data.scrollPos = scroller.scrollLeft; @@ -218,14 +269,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns position of child of scroller for specified orientation. * - * @param {HTMLElement} scroller scroller - * @param {HTMLElement} element child of scroller - * @param {boolean} vertical vertical scroll - * @return {number} child position + * @param {HTMLElement} scroller - Scroller. + * @param {HTMLElement} element - Child of scroller. + * @param {boolean} vertical - Vertical scroll. + * @return {number} Child position. */ function getScrollerChildPos(scroller, element, vertical) { - var elementRect = element.getBoundingClientRect(); - var scrollerRect = scroller.getBoundingClientRect(); + const elementRect = element.getBoundingClientRect(); + const scrollerRect = scroller.getBoundingClientRect(); if (!vertical) { return scroller.scrollLeft + elementRect.left - scrollerRect.left; @@ -237,21 +288,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns scroll position for element. * - * @param {ScrollerData} scrollerData scroller data - * @param {number} elementPos child element position - * @param {number} elementSize child element size - * @param {boolean} centered scroll to center - * @return {number} scroll position + * @param {ScrollerData} scrollerData - Scroller data. + * @param {number} elementPos - Child element position. + * @param {number} elementSize - Child element size. + * @param {boolean} centered - Scroll to center. + * @return {number} Scroll position. */ function calcScroll(scrollerData, elementPos, elementSize, centered) { - var maxScroll = scrollerData.scrollSize - scrollerData.clientSize; + const maxScroll = scrollerData.scrollSize - scrollerData.clientSize; - var scroll; + let scroll; if (centered) { scroll = elementPos + (elementSize - scrollerData.clientSize) / 2; } else { - var delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1); + const delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1); scroll = scrollerData.scrollPos - delta; } @@ -261,14 +312,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Calls scrollTo function in proper way. * - * @param {HTMLElement} scroller scroller - * @param {ScrollToOptions} options scroll options + * @param {HTMLElement} scroller - Scroller. + * @param {ScrollToOptions} options - Scroll options. */ function scrollToHelper(scroller, options) { if ("scrollTo" in scroller) { if (!supportsScrollToOptions) { - var scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft); - var scrollY = (options.top !== undefined ? options.top : scroller.scrollTop); + const scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft); + const scrollY = (options.top !== undefined ? options.top : scroller.scrollTop); scroller.scrollTo(scrollX, scrollY); } else { scroller.scrollTo(options); @@ -286,14 +337,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs built-in scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate - * @param {boolean} smooth smooth scrolling + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} smooth - Smooth scrolling. */ function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) { - var scrollBehavior = smooth ? "smooth" : "instant"; + const scrollBehavior = smooth ? "smooth" : "instant"; if (xScroller !== yScroller) { scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior}); @@ -303,7 +354,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage } } - var scrollTimer; + /** + * Requested frame for animated scroll. + */ + let scrollTimer; /** * Resets scroll timer to stop scrolling. @@ -316,29 +370,29 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs animated scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. */ function animateScroll(xScroller, scrollX, yScroller, scrollY) { - var ox = xScroller.scrollLeft; - var oy = yScroller.scrollTop; - var dx = scrollX - ox; - var dy = scrollY - oy; + const ox = xScroller.scrollLeft; + const oy = yScroller.scrollTop; + const dx = scrollX - ox; + const dy = scrollY - oy; if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) { return; } - var start; + let start; function scrollAnim(currentTimestamp) { start = start || currentTimestamp; - var k = Math.min(1, (currentTimestamp - start) / ScrollTime); + let k = Math.min(1, (currentTimestamp - start) / ScrollTime); if (k === 1) { resetScrollTimer(); @@ -348,8 +402,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage k = ease(k); - var x = ox + dx*k; - var y = oy + dy*k; + const x = ox + dx*k; + const y = oy + dy*k; builtinScroll(xScroller, x, yScroller, y, false); @@ -362,11 +416,11 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate - * @param {boolean} smooth smooth scrolling + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} smooth - Smooth scrolling. */ function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) { @@ -403,26 +457,26 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns true if scroll manager is enabled. */ - var isEnabled = function() { + export function isEnabled() { return layoutManager.tv; - }; + } /** * Scrolls the document to a given position. * - * @param {number} scrollX horizontal coordinate - * @param {number} scrollY vertical coordinate - * @param {boolean} [smooth=false] smooth scrolling + * @param {number} scrollX - Horizontal coordinate. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} [smooth=false] - Smooth scrolling. */ - var scrollTo = function(scrollX, scrollY, smooth) { + export function scrollTo(scrollX, scrollY, smooth) { smooth = !!smooth; // Scroller is document itself by default - var scroller = getScrollableParent(null, false); + const scroller = getScrollableParent(null, false); - var xScrollerData = getScrollerData(scroller, false); - var yScrollerData = getScrollerData(scroller, true); + const xScrollerData = getScrollerData(scroller, false); + const yScrollerData = getScrollerData(scroller, true); scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize); scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize); @@ -433,39 +487,39 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Scrolls the document to a given element. * - * @param {HTMLElement} element target element of scroll task - * @param {boolean} [smooth=false] smooth scrolling + * @param {HTMLElement} element - Target element of scroll task. + * @param {boolean} [smooth=false] - Smooth scrolling. */ - var scrollToElement = function(element, smooth) { + export function scrollToElement(element, smooth) { smooth = !!smooth; - var scrollCenterX = true; - var scrollCenterY = true; + let scrollCenterX = true; + let scrollCenterY = true; - var offsetParent = element.offsetParent; + const offsetParent = element.offsetParent; // In Firefox offsetParent.offsetParent is BODY - var isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed"); + const isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed"); // Scroll fixed elements to nearest edge (or do not scroll at all) if (isFixed) { scrollCenterX = scrollCenterY = false; } - var xScroller = getScrollableParent(element, false); - var yScroller = getScrollableParent(element, true); + const xScroller = getScrollableParent(element, false); + const yScroller = getScrollableParent(element, true); - var elementRect = element.getBoundingClientRect(); + const elementRect = element.getBoundingClientRect(); - var xScrollerData = getScrollerData(xScroller, false); - var yScrollerData = getScrollerData(yScroller, true); + const xScrollerData = getScrollerData(xScroller, false); + const yScrollerData = getScrollerData(yScroller, true); - var xPos = getScrollerChildPos(xScroller, element, false); - var yPos = getScrollerChildPos(yScroller, element, true); + const xPos = getScrollerChildPos(xScroller, element, false); + const yPos = getScrollerChildPos(yScroller, element, true); - var scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX); - var scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY); + const scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX); + let scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY); // HACK: Scroll to top for top menu because it is hidden // FIXME: Need a marker to scroll top/bottom @@ -490,9 +544,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage }, {capture: true}); } - return { + export default { isEnabled: isEnabled, scrollTo: scrollTo, scrollToElement: scrollToElement }; -}); diff --git a/src/components/skinManager.js b/src/components/skinManager.js index b81e7c3a40..d5b045c44e 100644 --- a/src/components/skinManager.js +++ b/src/components/skinManager.js @@ -116,8 +116,8 @@ define(['apphost', 'userSettings', 'browser', 'events', 'pluginManager', 'backdr var linkUrl = info.stylesheetPath; unloadTheme(); - var link = document.createElement('link'); + var link = document.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.onload = function () { diff --git a/src/components/subtitlesettings/subtitlesettings.js b/src/components/subtitlesettings/subtitlesettings.js index 69de536e4c..2c86929192 100644 --- a/src/components/subtitlesettings/subtitlesettings.js +++ b/src/components/subtitlesettings/subtitlesettings.js @@ -2,15 +2,11 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi "use strict"; function populateLanguages(select, languages) { - var html = ""; html += ""; - for (var i = 0, length = languages.length; i < length; i++) { - var culture = languages[i]; - html += ""; } @@ -18,7 +14,6 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi } function getSubtitleAppearanceObject(context) { - var appearanceSettings = {}; appearanceSettings.textSize = context.querySelector('#selectTextSize').value; @@ -102,14 +97,12 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi } function onSubmit(e) { - var self = this; var apiClient = connectionManager.getApiClient(self.options.serverId); var userId = self.options.userId; var userSettings = self.options.userSettings; userSettings.setUserInfo(userId, apiClient).then(function () { - var enableSaveConfirmation = self.options.enableSaveConfirmation; save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation); }); @@ -118,6 +111,7 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi if (e) { e.preventDefault(); } + return false; } @@ -197,9 +191,7 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi var userSettings = self.options.userSettings; apiClient.getUser(userId).then(function (user) { - userSettings.setUserInfo(userId, apiClient).then(function () { - self.dataLoaded = true; var appearanceSettings = userSettings.getSubtitleAppearanceSettings(self.options.appearanceKey); @@ -214,7 +206,6 @@ define(['require', 'globalize', 'appSettings', 'apphost', 'focusManager', 'loadi }; SubtitleSettings.prototype.destroy = function () { - this.options = null; }; diff --git a/src/components/subtitlesettings/subtitlesettings.template.html b/src/components/subtitlesettings/subtitlesettings.template.html index cc2788397f..716296a257 100644 --- a/src/components/subtitlesettings/subtitlesettings.template.html +++ b/src/components/subtitlesettings/subtitlesettings.template.html @@ -1,7 +1,5 @@
-
-

${Subtitles}

@@ -9,6 +7,7 @@
+
@@ -34,7 +34,6 @@
-

${HeaderSubtitleAppearance}

@@ -61,6 +60,7 @@
+
+
+
+