diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index bf4234ec97..bb2a09f176 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -59,7 +59,15 @@ jobs: pool: vmImage: 'ubuntu-latest' + variables: + - name: JellyfinVersion + value: 0.0.0 + steps: + - script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )" + displayName: Set release version (stable) + condition: startsWith(variables['Build.SourceBranch'], 'refs/tags') + - task: Docker@2 displayName: 'Push Unstable Image' condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master') @@ -84,7 +92,7 @@ jobs: containerRegistry: Docker Hub tags: | stable-$(Build.BuildNumber) - stable + $(JellyfinVersion) - job: CollectArtifacts displayName: 'Collect Artifacts' diff --git a/.dependabot/config.yml b/.dependabot/config.yml index 02dfd18aac..4ee827471a 100644 --- a/.dependabot/config.yml +++ b/.dependabot/config.yml @@ -2,4 +2,4 @@ version: 1 update_configs: - package_manager: "javascript" directory: "/" - update_schedule: "weekly" + update_schedule: "live" diff --git a/.eslintrc.js b/.eslintrc.js index ab53f0f03d..765db89daa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,7 +28,7 @@ module.exports = { ], rules: { 'block-spacing': ['error'], - 'brace-style': ['error'], + 'brace-style': ['error', "1tbs", { "allowSingleLine": true }], 'comma-dangle': ['error', 'never'], 'comma-spacing': ['error'], 'eol-last': ['error'], @@ -39,7 +39,10 @@ module.exports = { 'no-multi-spaces': ['error'], 'no-multiple-empty-lines': ['error', { 'max': 1 }], 'no-trailing-spaces': ['error'], + 'no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }], + "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], 'one-var': ['error', 'never'], + 'padded-blocks': ['error', 'never'], 'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }], 'semi': ['error'], 'space-before-blocks': ['error'], @@ -98,9 +101,8 @@ module.exports = { }, rules: { // TODO: Fix warnings and remove these rules - 'no-redeclare': ['warn'], - 'no-unused-vars': ['warn'], - 'no-useless-escape': ['warn'], + 'no-redeclare': ['off'], + 'no-useless-escape': ['off'], // TODO: Remove after ES6 migration is complete 'import/no-unresolved': ['off'] }, @@ -193,4 +195,4 @@ module.exports = { } } ] -} +}; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a35eb9981f..186dbcd12c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,6 @@ .ci @dkanada @EraYaN .github @jellyfin/core -build.sh @joshuaboniface +fedora @joshuaboniface +debian @joshuaboniface +.copr @joshuaboniface deployment @joshuaboniface diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md similarity index 67% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/1-bug-report.md index 137a689e8b..15efff9954 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/1-bug-report.md @@ -1,23 +1,20 @@ --- -name: Bug report -about: Create a bug report -title: '' +name: Bug Report +about: You have noticed a general issue or regression, and would like to report it labels: bug -assignees: '' - --- -**Describe the bug** +**Describe The Bug** -**To Reproduce** +**Steps To Reproduce** 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +**Expected Behavior** **Logs** @@ -27,9 +24,9 @@ assignees: '' **System (please complete the following information):** - - OS: [e.g. Docker, Debian, Windows] + - Platform: [e.g. Linux, Windows, iPhone, Tizen] - Browser: [e.g. Firefox, Chrome, Safari] - - Jellyfin Version: [e.g. 10.0.1] + - Jellyfin Version: [e.g. 10.6.0] -**Additional context** +**Additional Context** diff --git a/.github/ISSUE_TEMPLATE/2-playback-issue.md b/.github/ISSUE_TEMPLATE/2-playback-issue.md new file mode 100644 index 0000000000..bed7315abb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-playback-issue.md @@ -0,0 +1,22 @@ +--- +name: Playback Issue +about: You have playback issues with some files +labels: playback +--- + +**Describe The Bug** + + +**Media Information** + + +**Screenshots** + + +**System (please complete the following information):** + - Platform: [e.g. Linux, Windows, iPhone, Tizen] + - Browser: [e.g. Firefox, Chrome, Safari] + - Jellyfin Version: [e.g. 10.6.0] + +**Additional Context** + diff --git a/.github/ISSUE_TEMPLATE/3-technical-discussion.md b/.github/ISSUE_TEMPLATE/3-technical-discussion.md new file mode 100644 index 0000000000..d8140fce75 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-technical-discussion.md @@ -0,0 +1,13 @@ +--- +name: Technical Discussion +about: You want to discuss technical aspects of changes you intend to make +labels: enhancement +--- + + diff --git a/.github/ISSUE_TEMPLATE/4-meta-issue.md b/.github/ISSUE_TEMPLATE/4-meta-issue.md new file mode 100644 index 0000000000..e034302e45 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-meta-issue.md @@ -0,0 +1,9 @@ +--- +name: Meta Issue +about: You want to track a number of other issues as part of a larger project +labels: meta +--- + +* [ ] Issue 1 [#123] +* [ ] Issue 2 [#456] +* [ ] ... diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..2ed06fae39 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Feature Request + url: https://features.jellyfin.org/ + about: Please head over to our feature request hub to vote on or submit a feature. + - name: Help Or Question + url: https://matrix.to/#/#jellyfin-troubleshooting:matrix.org + about: Please join the troubleshooting Matrix channel to get some help. diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 0000000000..a62bc7522a --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,24 @@ +# Support + +Jellyfin contributors have limited availability to address general support +questions. Please make sure you are using the latest version of Jellyfin. + +When looking for support or information, please first search for your +question in these venues: + +* [Jellyfin Forum](https://forum.jellyfin.org) +* [Jellyfin Documentation](https://docs.jellyfin.org) +* [Open or **closed** issues in the organization](https://github.com/issues?q=sort%3Aupdated-desc+org%3Ajellyfin+is%3Aissue+) + +If you didn't find an answer in the resources above, contributors and other +users are reachable through the following channels: + +* #jellyfin on [Matrix](https://matrix.to/#/#jellyfin:matrix.org%22) or [IRC](https://webchat.freenode.net/#jellyfin) +* #jellyfin-troubleshooting on [Matrix](https://matrix.to/#/#jellyfin-troubleshooting:matrix.org) or [IRC](https://webchat.freenode.net/#jellyfin-troubleshooting) +* [/r/jellyfin on Reddit](https://www.reddit.com/r/jellyfin) + +GitHub issues are for tracking enhancements and bugs, not general support. + +The open source license grants you the freedom to use Jellyfin. +It does not guarantee commitments of other people's time. +Please be respectful and manage your expectations. diff --git a/README.md b/README.md index f06e461320..ca42965dd9 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Jellyfin Web is the frontend used for most of the clients available for end user ### Dependencies +- [Node.js](https://nodejs.org/en/download/) - [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install) - Gulp-cli diff --git a/build.yaml b/build.yaml index fe1633faec..a73be8ec43 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- # We just wrap `build` so this is really it name: "jellyfin-web" -version: "10.6.0" +version: "10.7.0" packages: - debian.all - fedora.all diff --git a/bump_version b/bump_version index bc8288b829..4e6aa6f792 100755 --- a/bump_version +++ b/bump_version @@ -4,6 +4,7 @@ set -o errexit set -o pipefail +set -o xtrace usage() { echo -e "bump_version - increase the shared version and generate changelogs" @@ -23,10 +24,7 @@ build_file="./build.yaml" new_version="$1" # Parse the version from shared version file -old_version="$( - grep "appVersion" ${shared_version_file} | head -1 \ - | sed -E 's/var appVersion = "([0-9\.]+)";/\1/' -)" +old_version="$( grep "appVersion" ${shared_version_file} | head -1 | sed -E "s/var appVersion = '([0-9\.]+)';/\1/" | tr -d '[:space:]' )" echo "Old version in appHost is: $old_version" # Set the shared version to the specified new_version @@ -34,11 +32,8 @@ old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' cha new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )" sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file} -old_version="$( - grep "version:" ${build_file} \ - | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' -)" -echo "Old version in ${build_file}: $old_version`" +old_version="$( grep "version:" ${build_file} | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' )" +echo "Old version in ${build_file}: ${old_version}" # Set the build.yaml version to the specified new_version old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars @@ -54,7 +49,7 @@ fi debian_changelog_file="debian/changelog" debian_changelog_temp="$( mktemp )" # Create new temp file with our changelog -echo -e "jellyfin (${new_version_deb}) unstable; urgency=medium +echo -e "jellyfin-web (${new_version_deb}) unstable; urgency=medium * New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version} @@ -65,15 +60,15 @@ cat ${debian_changelog_file} >> ${debian_changelog_temp} mv ${debian_changelog_temp} ${debian_changelog_file} # Write out a temporary Yum changelog with our new stuff prepended and some templated formatting -fedora_spec_file="fedora/jellyfin.spec" +fedora_spec_file="fedora/jellyfin-web.spec" fedora_changelog_temp="$( mktemp )" fedora_spec_temp_dir="$( mktemp -d )" -fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin.spec.tmp" +fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin-web.spec.tmp" # Make a copy of our spec file for hacking cp ${fedora_spec_file} ${fedora_spec_temp_dir}/ pushd ${fedora_spec_temp_dir} # Split out the stuff before and after changelog -csplit jellyfin.spec "/^%changelog/" # produces xx00 xx01 +csplit jellyfin-web.spec "/^%changelog/" # produces xx00 xx01 # Update the version in xx00 sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00 # Remove the header from xx01 @@ -92,5 +87,5 @@ mv ${fedora_spec_temp} ${fedora_spec_file} rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir} # Stage the changed files for commit -git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} Dockerfile* +git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} git status diff --git a/debian/changelog b/debian/changelog index 50966c3a01..ab5e13196d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +jellyfin-web (10.7.0-1) unstable; urgency=medium + + * Forthcoming stable release + + -- Jellyfin Packaging Team Mon, 27 Jul 2020 19:13:31 -0400 + jellyfin-web (10.6.0-1) unstable; urgency=medium * New upstream version 10.6.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.0 diff --git a/fedora/jellyfin-web.spec b/fedora/jellyfin-web.spec index dcc9d9d2ab..b8c77f2a1f 100644 --- a/fedora/jellyfin-web.spec +++ b/fedora/jellyfin-web.spec @@ -1,7 +1,7 @@ %global debug_package %{nil} Name: jellyfin-web -Version: 10.6.0 +Version: 10.7.0 Release: 1%{?dist} Summary: The Free Software Media System web client License: GPLv3 @@ -39,5 +39,7 @@ mv dist %{buildroot}%{_datadir}/jellyfin-web %{_datadir}/licenses/jellyfin/LICENSE %changelog +* Mon Jul 27 2020 Jellyfin Packaging Team +- Forthcoming stable release * Mon Mar 23 2020 Jellyfin Packaging Team - Forthcoming stable release diff --git a/package.json b/package.json index 52ead1b36e..de3a777e2b 100644 --- a/package.json +++ b/package.json @@ -5,18 +5,18 @@ "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2.0-or-later", "devDependencies": { - "@babel/core": "^7.10.3", + "@babel/core": "^7.10.5", "@babel/plugin-proposal-class-properties": "^7.10.1", "@babel/plugin-proposal-private-methods": "^7.10.1", - "@babel/plugin-transform-modules-amd": "^7.9.6", + "@babel/plugin-transform-modules-amd": "^7.10.5", "@babel/polyfill": "^7.8.7", "@babel/preset-env": "^7.10.3", "autoprefixer": "^9.8.5", "babel-eslint": "^11.0.0-beta.2", "babel-loader": "^8.0.6", - "browser-sync": "^2.26.7", + "browser-sync": "^2.26.12", "copy-webpack-plugin": "^5.1.1", - "css-loader": "^3.6.0", + "css-loader": "^4.0.0", "cssnano": "^4.1.10", "del": "^5.1.0", "eslint": "^6.8.0", @@ -37,7 +37,7 @@ "gulp-postcss": "^8.0.0", "gulp-sass": "^4.0.2", "gulp-sourcemaps": "^2.6.5", - "gulp-terser": "^1.2.0", + "gulp-terser": "^1.2.1", "html-webpack-plugin": "^4.3.0", "lazypipe": "^1.0.2", "node-sass": "^4.13.1", @@ -48,7 +48,7 @@ "stylelint-config-rational-order": "^0.1.2", "stylelint-no-browser-hacks": "^1.2.1", "stylelint-order": "^4.1.0", - "webpack": "^4.41.5", + "webpack": "^4.44.0", "webpack-merge": "^4.2.2", "webpack-stream": "^5.2.1" }, @@ -57,15 +57,15 @@ "blurhash": "^1.1.3", "classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz", "core-js": "^3.6.5", - "date-fns": "^2.14.0", + "date-fns": "^2.15.0", "epubjs": "^0.3.85", "fast-text-encoding": "^1.0.3", "flv.js": "^1.5.0", "headroom.js": "^0.11.0", - "hls.js": "^0.14.0", + "hls.js": "^0.14.6", "howler": "^2.2.0", "intersection-observer": "^0.11.0", - "jellyfin-apiclient": "^1.3.0", + "jellyfin-apiclient": "^1.4.1", "jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto", "jquery": "^3.5.1", "jstree": "^3.3.10", @@ -76,7 +76,6 @@ "query-string": "^6.13.1", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.2", - "shaka-player": "^2.5.13", "sortablejs": "^1.10.2", "swiper": "^5.4.5", "webcomponents.js": "^0.7.24", @@ -91,13 +90,48 @@ "test": [ "src/components/accessSchedule/accessSchedule.js", "src/components/actionSheet/actionSheet.js", + "src/components/activitylog.js", + "src/components/alert.js", + "src/components/alphaPicker/alphaPicker.js", + "src/components/appFooter/appFooter.js", "src/components/autoFocuser.js", + "src/components/backdrop/backdrop.js", "src/components/cardbuilder/cardBuilder.js", "src/components/cardbuilder/chaptercardbuilder.js", "src/components/cardbuilder/peoplecardbuilder.js", + "src/components/channelMapper/channelMapper.js", + "src/components/collectionEditor/collectionEditor.js", + "src/components/confirm/confirm.js", + "src/components/dialog/dialog.js", + "src/components/dialogHelper/dialogHelper.js", + "src/components/directorybrowser/directorybrowser.js", + "src/components/displaySettings/displaySettings.js", + "src/components/fetchhelper.js", + "src/components/filterdialog/filterdialog.js", + "src/components/groupedcards.js", + "src/components/homeScreenSettings/homeScreenSettings.js", + "src/components/homesections/homesections.js", + "src/components/htmlMediaHelper.js", + "src/components/imageOptionsEditor/imageOptionsEditor.js", "src/components/images/imageLoader.js", + "src/components/imageDownloader/imageDownloader.js", + "src/components/imageeditor/imageeditor.js", + "src/components/imageUploader/imageUploader.js", "src/components/indicators/indicators.js", + "src/components/itemContextMenu.js", + "src/components/itemidentifier/itemidentifier.js", + "src/components/itemMediaInfo/itemMediaInfo.js", "src/components/lazyLoader/lazyLoaderIntersectionObserver.js", + "src/components/libraryoptionseditor/libraryoptionseditor.js", + "src/components/listview/listview.js", + "src/components/maintabsmanager.js", + "src/components/mediainfo/mediainfo.js", + "src/components/mediaLibraryCreator/mediaLibraryCreator.js", + "src/components/mediaLibraryEditor/mediaLibraryEditor.js", + "src/components/metadataEditor/metadataEditor.js", + "src/components/metadataEditor/personEditor.js", + "src/components/multiSelect/multiSelect.js", + "src/components/nowPlayingBar/nowPlayingBar.js", "src/components/playback/brightnessosd.js", "src/components/playback/mediasession.js", "src/components/playback/nowplayinghelper.js", @@ -107,13 +141,38 @@ "src/components/playback/playmethodhelper.js", "src/components/playback/remotecontrolautoplay.js", "src/components/playback/volumeosd.js", + "src/components/playbackSettings/playbackSettings.js", + "src/components/playerstats/playerstats.js", + "src/components/playlisteditor/playlisteditor.js", "src/components/playmenu.js", + "src/components/prompt/prompt.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", + "src/components/search/searchfields.js", + "src/components/search/searchresults.js", + "src/components/settingshelper.js", + "src/components/shortcuts.js", + "src/components/subtitlesettings/subtitleappearancehelper.js", + "src/components/subtitlesettings/subtitlesettings.js", "src/components/syncPlay/groupSelectionMenu.js", "src/components/syncPlay/playbackPermissionManager.js", "src/components/syncPlay/syncPlayManager.js", "src/components/syncPlay/timeSyncManager.js", + "src/controllers/session/addServer/index.js", + "src/controllers/session/forgotPassword/index.js", + "src/controllers/session/redeemPassword/index.js", + "src/controllers/session/login/index.js", + "src/controllers/session/selectServer/index.js", + "src/controllers/dashboard/apikeys.js", + "src/controllers/dashboard/dashboard.js", + "src/controllers/dashboard/devices/device.js", + "src/controllers/dashboard/devices/devices.js", + "src/controllers/dashboard/dlna/profile.js", + "src/controllers/dashboard/dlna/profiles.js", + "src/controllers/dashboard/dlna/settings.js", + "src/controllers/dashboard/encodingsettings.js", + "src/controllers/dashboard/general.js", + "src/controllers/dashboard/librarydisplay.js", "src/controllers/dashboard/logs.js", "src/controllers/dashboard/plugins/repositories.js", "src/controllers/music/musicalbums.js", @@ -126,23 +185,91 @@ "src/controllers/user/home.js", "src/controllers/user/playback.js", "src/controllers/user/subtitles.js", + "src/controllers/dashboard/mediaLibrary.js", + "src/controllers/dashboard/metadataImages.js", + "src/controllers/dashboard/metadatanfo.js", + "src/controllers/dashboard/networking.js", + "src/controllers/dashboard/playback.js", + "src/controllers/dashboard/plugins/repositories/index.js", + "src/controllers/dashboard/scheduledtasks/scheduledtask.js", + "src/controllers/dashboard/scheduledtasks/scheduledtasks.js", + "src/controllers/dashboard/serveractivity.js", + "src/controllers/dashboard/streaming.js", + "src/controllers/dashboard/users/useredit.js", + "src/controllers/dashboard/users/userlibraryaccess.js", + "src/controllers/dashboard/users/usernew.js", + "src/controllers/dashboard/users/userparentalcontrol.js", + "src/controllers/dashboard/users/userpasswordpage.js", + "src/controllers/dashboard/users/userprofilespage.js", + "src/controllers/playback/queue/index.js", + "src/controllers/playback/video/index.js", + "src/controllers/searchpage.js", + "src/controllers/shows/episodes.js", + "src/controllers/shows/tvgenres.js", + "src/controllers/shows/tvlatest.js", + "src/controllers/shows/tvrecommended.js", + "src/controllers/shows/tvshows.js", + "src/controllers/shows/tvstudios.js", + "src/controllers/shows/tvupcoming.js", + "src/controllers/user/display/index.js", + "src/controllers/user/home/index.js", + "src/controllers/user/menu/index.js", + "src/controllers/user/playback/index.js", + "src/controllers/user/profile/index.js", + "src/controllers/user/subtitles/index.js", + "src/controllers/user/subtitles/index.js", + "src/controllers/wizard/finish/index.js", + "src/controllers/wizard/remote/index.js", + "src/controllers/wizard/settings/index.js", + "src/controllers/wizard/start/index.js", + "src/controllers/wizard/user/index.js", + "src/elements/emby-button/emby-button.js", + "src/elements/emby-button/paper-icon-button-light.js", + "src/elements/emby-checkbox/emby-checkbox.js", + "src/elements/emby-collapse/emby-collapse.js", + "src/elements/emby-input/emby-input.js", + "src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js", + "src/elements/emby-itemscontainer/emby-itemscontainer.js", + "src/elements/emby-playstatebutton/emby-playstatebutton.js", + "src/elements/emby-programcell/emby-programcell.js", + "src/elements/emby-progressbar/emby-progressbar.js", + "src/elements/emby-progressring/emby-progressring.js", + "src/elements/emby-radio/emby-radio.js", + "src/elements/emby-ratingbutton/emby-ratingbutton.js", + "src/elements/emby-scrollbuttons/emby-scrollbuttons.js", + "src/elements/emby-scroller/emby-scroller.js", + "src/elements/emby-select/emby-select.js", + "src/elements/emby-slider/emby-slider.js", + "src/elements/emby-tabs/emby-tabs.js", + "src/elements/emby-textarea/emby-textarea.js", + "src/elements/emby-toggle/emby-toggle.js", + "src/plugins/backdropScreensaver/plugin.js", "src/plugins/bookPlayer/plugin.js", "src/plugins/bookPlayer/tableOfContents.js", "src/plugins/photoPlayer/plugin.js", + "src/plugins/youtubePlayer/plugin.js", + "src/scripts/alphanumericshortcuts.js", + "src/scripts/autoBackdrops.js", + "src/scripts/datetime.js", "src/scripts/deleteHelper.js", "src/scripts/dfnshelper.js", "src/scripts/dom.js", + "src/scripts/editorsidebar.js", "src/scripts/fileDownloader.js", "src/scripts/filesystem.js", + "src/scripts/globalize.js", "src/scripts/imagehelper.js", "src/scripts/inputManager.js", - "src/plugins/backdropScreensaver/plugin.js", - "src/components/filterdialog/filterdialog.js", - "src/components/fetchhelper.js", "src/scripts/keyboardNavigation.js", + "src/scripts/libraryBrowser.js", + "src/scripts/multiDownload.js", + "src/scripts/playlists.js", "src/scripts/settings/appSettings.js", "src/scripts/settings/userSettings.js", - "src/scripts/settings/webSettings.js" + "src/scripts/settings/webSettings.js", + "src/scripts/taskbutton.js", + "src/scripts/themeLoader.js", + "src/scripts/touchHelper.js" ], "plugins": [ "@babel/plugin-transform-modules-amd", @@ -157,7 +284,7 @@ "last 2 Chrome versions", "last 2 ChromeAndroid versions", "last 2 Safari versions", - "last 2 iOS versions", + "iOS > 10", "last 2 Edge versions", "Chrome 27", "Chrome 38", @@ -165,6 +292,7 @@ "Chrome 53", "Chrome 56", "Chrome 63", + "Edge 18", "Firefox ESR" ], "scripts": { diff --git a/src/assets/css/site.css b/src/assets/css/site.css index 1a8873ba97..38e056df89 100644 --- a/src/assets/css/site.css +++ b/src/assets/css/site.css @@ -129,3 +129,17 @@ div[data-role=page] { .hide-scroll { overflow-y: hidden; } + +.w-100 { + width: 100%; +} + +.margin-auto-x { + margin-left: auto; + margin-right: auto; +} + +.margin-auto-y { + margin-top: auto; + margin-bottom: auto; +} diff --git a/src/assets/img/devices/edgechromium.svg b/src/assets/img/devices/edgechromium.svg new file mode 100644 index 0000000000..14d68a5d48 --- /dev/null +++ b/src/assets/img/devices/edgechromium.svg @@ -0,0 +1 @@ +Microsoft Edge icon diff --git a/src/bundle.js b/src/bundle.js index dd1ff6548b..ae2a59f0d5 100644 --- a/src/bundle.js +++ b/src/bundle.js @@ -78,12 +78,6 @@ _define('webcomponents', function() { return webcomponents; }); -// shaka -var shaka = require('shaka-player'); -_define('shaka', function() { - return shaka; -}); - // libass-wasm var libassWasm = require('libass-wasm'); _define('JavascriptSubtitlesOctopus', function() { diff --git a/src/components/accessSchedule/accessSchedule.js b/src/components/accessSchedule/accessSchedule.js index 166460a025..6b96aad1d4 100644 --- a/src/components/accessSchedule/accessSchedule.js +++ b/src/components/accessSchedule/accessSchedule.js @@ -59,15 +59,14 @@ import 'formDialogStyle'; export function show(options) { return new Promise((resolve, reject) => { - // TODO: remove require - require(['text!./components/accessSchedule/accessSchedule.template.html'], template => { + import('text!./accessSchedule.template.html').then(({default: template}) => { const dlg = dialogHelper.createDialog({ removeOnClose: true, size: 'small' }); dlg.classList.add('formDialog'); let html = ''; - html += globalize.translateDocument(template); + html += globalize.translateHtml(template); dlg.innerHTML = html; populateHours(dlg); loadSchedule(dlg, options.schedule); diff --git a/src/components/actionSheet/actionSheet.js b/src/components/actionSheet/actionSheet.js index 2e22111945..937cd2afe5 100644 --- a/src/components/actionSheet/actionSheet.js +++ b/src/components/actionSheet/actionSheet.js @@ -9,7 +9,6 @@ import 'scrollStyles'; import 'listViewStyle'; function getOffsets(elems) { - let results = []; if (!document) { @@ -31,7 +30,6 @@ function getOffsets(elems) { } function getPosition(options, dlg) { - const windowSize = dom.getWindowSize(); const windowHeight = windowSize.innerHeight; const windowWidth = windowSize.innerWidth; @@ -73,14 +71,13 @@ function getPosition(options, dlg) { } function centerFocus(elem, horiz, on) { - require(['scrollHelper'], function (scrollHelper) { + import('scrollHelper').then(({default: scrollHelper}) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); } export function show(options) { - // items // positionTo // showCancel @@ -98,7 +95,6 @@ export function show(options) { isFullscreen = true; dialogOptions.autoFocus = true; } else { - dialogOptions.modal = false; dialogOptions.entryAnimation = options.entryAnimation; dialogOptions.exitAnimation = options.exitAnimation; @@ -136,7 +132,6 @@ export function show(options) { let icons = []; let itemIcon; for (const item of options.items) { - itemIcon = item.icon || (item.selected ? 'check' : null); if (itemIcon) { @@ -161,7 +156,6 @@ export function show(options) { } if (options.title) { - html += '

' + options.title + '

'; } if (options.text) { @@ -197,7 +191,6 @@ export function show(options) { const item = options.items[i]; if (item.divider) { - html += '
'; continue; } @@ -255,8 +248,6 @@ export function show(options) { }); } - // Seeing an issue in some non-chrome browsers where this is requiring a double click - //var eventName = browser.firefox ? 'mousedown' : 'click'; let selectedId; let timeout; @@ -267,26 +258,20 @@ export function show(options) { } return new Promise(function (resolve, reject) { - let isResolved; dlg.addEventListener('click', function (e) { - const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem'); if (actionSheetMenuItem) { selectedId = actionSheetMenuItem.getAttribute('data-id'); if (options.resolveOnClick) { - if (options.resolveOnClick.indexOf) { - if (options.resolveOnClick.indexOf(selectedId) !== -1) { - resolve(selectedId); isResolved = true; } - } else { resolve(selectedId); isResolved = true; @@ -295,11 +280,9 @@ export function show(options) { dialogHelper.close(dlg); } - }); dlg.addEventListener('close', function () { - if (layoutManager.tv) { centerFocus(dlg.querySelector('.actionSheetScroller'), false, false); } diff --git a/src/components/activitylog.js b/src/components/activitylog.js index bbb0995063..9834255003 100644 --- a/src/components/activitylog.js +++ b/src/components/activitylog.js @@ -1,11 +1,20 @@ -define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) { - 'use strict'; +import events from 'events'; +import globalize from 'globalize'; +import dom from 'dom'; +import * as datefns from 'date-fns'; +import dfnshelper from 'dfnshelper'; +import serverNotifications from 'serverNotifications'; +import connectionManager from 'connectionManager'; +import 'emby-button'; +import 'listViewStyle'; + +/* eslint-disable indent */ function getEntryHtml(entry, apiClient) { - var html = ''; + let html = ''; html += '
'; - var color = '#00a4dc'; - var icon = 'notifications'; + let color = '#00a4dc'; + let icon = 'notifications'; if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) { color = '#cc0000'; @@ -56,9 +65,10 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', } limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7'); - var minDate = new Date(); - var hasUserId = 'false' !== elem.getAttribute('data-useractivity'); + const minDate = new Date(); + const hasUserId = 'false' !== elem.getAttribute('data-useractivity'); + // TODO: Use date-fns if (hasUserId) { minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back } else { @@ -74,7 +84,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', elem.setAttribute('data-activitystartindex', startIndex); elem.setAttribute('data-activitylimit', limit); if (!startIndex) { - var activityContainer = dom.parentWithClass(elem, 'activityContainer'); + const activityContainer = dom.parentWithClass(elem, 'activityContainer'); if (activityContainer) { if (result.Items.length) { @@ -91,7 +101,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', } function onActivityLogUpdate(e, apiClient, data) { - var options = this.options; + const options = this.options; if (options && options.serverId === apiClient.serverId()) { reloadData(this, options.element, apiClient); @@ -99,14 +109,14 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', } function onListClick(e) { - var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo'); + const btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo'); if (btnEntryInfo) { - var id = btnEntryInfo.getAttribute('data-id'); - var items = this.items; + const id = btnEntryInfo.getAttribute('data-id'); + const items = this.items; if (items) { - var item = items.filter(function (i) { + const item = items.filter(function (i) { return i.Id.toString() === id; })[0]; @@ -118,35 +128,35 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', } function showItemOverview(item) { - require(['alert'], function (alert) { + import('alert').then(({default: alert}) => { alert({ text: item.Overview }); }); } - function ActivityLog(options) { +class ActivityLog { + constructor(options) { this.options = options; - var element = options.element; + const element = options.element; element.classList.add('activityLogListWidget'); element.addEventListener('click', onListClick.bind(this)); - var apiClient = connectionManager.getApiClient(options.serverId); + const apiClient = connectionManager.getApiClient(options.serverId); reloadData(this, element, apiClient); - var onUpdate = onActivityLogUpdate.bind(this); + const onUpdate = onActivityLogUpdate.bind(this); this.updateFn = onUpdate; events.on(serverNotifications, 'ActivityLogEntry', onUpdate); apiClient.sendMessage('ActivityLogEntryStart', '0,1500'); } - - ActivityLog.prototype.destroy = function () { - var options = this.options; + destroy() { + const options = this.options; if (options) { options.element.classList.remove('activityLogListWidget'); connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500'); } - var onUpdate = this.updateFn; + const onUpdate = this.updateFn; if (onUpdate) { events.off(serverNotifications, 'ActivityLogEntry', onUpdate); @@ -154,7 +164,9 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', this.items = null; this.options = null; - }; + } +} - return ActivityLog; -}); +export default ActivityLog; + +/* eslint-enable indent */ diff --git a/src/components/alert.js b/src/components/alert.js index 8a37ac1845..1420c7f428 100644 --- a/src/components/alert.js +++ b/src/components/alert.js @@ -1,14 +1,16 @@ -define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) { - 'use strict'; +import browser from 'browser'; +import dialog from 'dialog'; +import globalize from 'globalize'; + +/* eslint-disable indent */ function replaceAll(originalString, strReplace, strWith) { - var reg = new RegExp(strReplace, 'ig'); + const reg = new RegExp(strReplace, 'ig'); return originalString.replace(reg, strWith); } - return function (text, title) { - - var options; + export default function (text, title) { + let options; if (typeof text === 'string') { options = { title: title, @@ -21,7 +23,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) if (browser.tv && window.alert) { alert(replaceAll(options.text || '', '
', '\n')); } else { - var items = []; + const items = []; items.push({ name: globalize.translate('ButtonGotIt'), @@ -31,7 +33,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) options.buttons = items; - return dialog(options).then(function (result) { + return dialog.show(options).then(function (result) { if (result === 'ok') { return Promise.resolve(); } @@ -41,5 +43,6 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) } return Promise.resolve(); - }; -}); + } + +/* eslint-enable indent */ diff --git a/src/components/alphaPicker/alphaPicker.js b/src/components/alphaPicker/alphaPicker.js index 79f74879e5..95b5881677 100644 --- a/src/components/alphaPicker/alphaPicker.js +++ b/src/components/alphaPicker/alphaPicker.js @@ -1,11 +1,22 @@ -define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager, layoutManager, dom) { - 'use strict'; +/* eslint-disable indent */ - var selectedButtonClass = 'alphaPickerButton-selected'; +/** + * Module alphaPicker. + * @module components/alphaPicker/alphaPicker + */ + +import focusManager from 'focusManager'; +import layoutManager from 'layoutManager'; +import dom from 'dom'; +import 'css!./style.css'; +import 'paper-icon-button-light'; +import 'material-icons'; + + const selectedButtonClass = 'alphaPickerButton-selected'; function focus() { - var scope = this; - var selected = scope.querySelector('.' + selectedButtonClass); + const scope = this; + const selected = scope.querySelector(`.${selectedButtonClass}`); if (selected) { focusManager.focus(selected); @@ -15,8 +26,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b } function getAlphaPickerButtonClassName(vertical) { - - var alphaPickerButtonClassName = 'alphaPickerButton'; + let alphaPickerButtonClassName = 'alphaPickerButton'; if (layoutManager.tv) { alphaPickerButtonClassName += ' alphaPickerButton-tv'; @@ -30,44 +40,42 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b } function getLetterButton(l, vertical) { - return ''; + return ``; } function mapLetters(letters, vertical) { - - return letters.map(function (l) { + return letters.map(l => { return getLetterButton(l, vertical); }); } function render(element, options) { - element.classList.add('alphaPicker'); if (layoutManager.tv) { element.classList.add('alphaPicker-tv'); } - var vertical = element.classList.contains('alphaPicker-vertical'); + const vertical = element.classList.contains('alphaPicker-vertical'); if (!vertical) { element.classList.add('focuscontainer-x'); } - var html = ''; - var letters; + let html = ''; + let letters; - var alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical); + const alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical); - var rowClassName = 'alphaPickerRow'; + let rowClassName = 'alphaPickerRow'; if (vertical) { rowClassName += ' alphaPickerRow-vertical'; } - html += '
'; + html += `
`; if (options.mode === 'keyboard') { - html += ''; + html += ``; } else { letters = ['#']; html += mapLetters(letters, vertical).join(''); @@ -77,11 +85,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b html += mapLetters(letters, vertical).join(''); if (options.mode === 'keyboard') { - html += ''; + html += ``; html += '
'; letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; - html += '
'; + html += `
`; html += '
'; html += mapLetters(letters, vertical).join(''); html += '
'; @@ -95,227 +103,211 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b element.focus = focus; } - function AlphaPicker(options) { + export class AlphaPicker { + constructor(options) { + const self = this; - var self = this; - this.options = options; + this.options = options; - var element = options.element; - var itemsContainer = options.itemsContainer; - var itemClass = options.itemClass; + const element = options.element; + const itemsContainer = options.itemsContainer; + const itemClass = options.itemClass; - var itemFocusValue; - var itemFocusTimeout; + let itemFocusValue; + let itemFocusTimeout; - function onItemFocusTimeout() { - itemFocusTimeout = null; - self.value(itemFocusValue); - } - - var alphaFocusedElement; - var alphaFocusTimeout; - - function onAlphaFocusTimeout() { - - alphaFocusTimeout = null; - - if (document.activeElement === alphaFocusedElement) { - var value = alphaFocusedElement.getAttribute('data-value'); - self.value(value, true); + function onItemFocusTimeout() { + itemFocusTimeout = null; + self.value(itemFocusValue); } - } - function onAlphaPickerInKeyboardModeClick(e) { + let alphaFocusedElement; + let alphaFocusTimeout; - var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); + function onAlphaFocusTimeout() { + alphaFocusTimeout = null; - if (alphaPickerButton) { - var value = alphaPickerButton.getAttribute('data-value'); - - element.dispatchEvent(new CustomEvent('alphavalueclicked', { - cancelable: false, - detail: { - value: value - } - })); - } - } - - function onAlphaPickerClick(e) { - - var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); - - if (alphaPickerButton) { - var value = alphaPickerButton.getAttribute('data-value'); - if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) { - self.value(null, true); - } else { + if (document.activeElement === alphaFocusedElement) { + const value = alphaFocusedElement.getAttribute('data-value'); self.value(value, true); } } - } - function onAlphaPickerFocusIn(e) { + function onAlphaPickerInKeyboardModeClick(e) { + const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); - if (alphaFocusTimeout) { - clearTimeout(alphaFocusTimeout); - alphaFocusTimeout = null; + if (alphaPickerButton) { + const value = alphaPickerButton.getAttribute('data-value'); + + element.dispatchEvent(new CustomEvent('alphavalueclicked', { + cancelable: false, + detail: { + value + } + })); + } } - var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); + function onAlphaPickerClick(e) { + const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); - if (alphaPickerButton) { - alphaFocusedElement = alphaPickerButton; - alphaFocusTimeout = setTimeout(onAlphaFocusTimeout, 600); - } - } - - function onItemsFocusIn(e) { - - var item = dom.parentWithClass(e.target, itemClass); - - if (item) { - var prefix = item.getAttribute('data-prefix'); - if (prefix && prefix.length) { - - itemFocusValue = prefix[0]; - if (itemFocusTimeout) { - clearTimeout(itemFocusTimeout); + if (alphaPickerButton) { + const value = alphaPickerButton.getAttribute('data-value'); + if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) { + this.value(null, true); + } else { + this.value(value, true); } - itemFocusTimeout = setTimeout(onItemFocusTimeout, 100); } } - } - self.enabled = function (enabled) { - - if (enabled) { - - if (itemsContainer) { - itemsContainer.addEventListener('focus', onItemsFocusIn, true); + function onAlphaPickerFocusIn(e) { + if (alphaFocusTimeout) { + clearTimeout(alphaFocusTimeout); + alphaFocusTimeout = null; } - if (options.mode === 'keyboard') { - element.addEventListener('click', onAlphaPickerInKeyboardModeClick); - } + const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); - if (options.valueChangeEvent !== 'click') { - element.addEventListener('focus', onAlphaPickerFocusIn, true); + if (alphaPickerButton) { + alphaFocusedElement = alphaPickerButton; + alphaFocusTimeout = setTimeout(onAlphaFocusTimeout, 600); + } + } + + function onItemsFocusIn(e) { + const item = dom.parentWithClass(e.target, itemClass); + + if (item) { + const prefix = item.getAttribute('data-prefix'); + if (prefix && prefix.length) { + itemFocusValue = prefix[0]; + if (itemFocusTimeout) { + clearTimeout(itemFocusTimeout); + } + itemFocusTimeout = setTimeout(onItemFocusTimeout, 100); + } + } + } + + this.enabled = function (enabled) { + if (enabled) { + if (itemsContainer) { + itemsContainer.addEventListener('focus', onItemsFocusIn, true); + } + + if (options.mode === 'keyboard') { + element.addEventListener('click', onAlphaPickerInKeyboardModeClick); + } + + if (options.valueChangeEvent !== 'click') { + element.addEventListener('focus', onAlphaPickerFocusIn, true); + } else { + element.addEventListener('click', onAlphaPickerClick.bind(this)); + } } else { - element.addEventListener('click', onAlphaPickerClick.bind(this)); - } - - } else { - - if (itemsContainer) { - itemsContainer.removeEventListener('focus', onItemsFocusIn, true); - } - - element.removeEventListener('click', onAlphaPickerInKeyboardModeClick); - element.removeEventListener('focus', onAlphaPickerFocusIn, true); - element.removeEventListener('click', onAlphaPickerClick.bind(this)); - } - }; - - render(element, options); - - this.enabled(true); - this.visible(true); - } - - AlphaPicker.prototype.value = function (value, applyValue) { - - var element = this.options.element; - var btn; - var selected; - - if (value !== undefined) { - if (value != null) { - - value = value.toUpperCase(); - this._currentValue = value; - - if (this.options.mode !== 'keyboard') { - selected = element.querySelector('.' + selectedButtonClass); - - try { - btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']'); - } catch (err) { - console.error('error in querySelector: ' + err); + if (itemsContainer) { + itemsContainer.removeEventListener('focus', onItemsFocusIn, true); } - if (btn && btn !== selected) { - btn.classList.add(selectedButtonClass); + element.removeEventListener('click', onAlphaPickerInKeyboardModeClick); + element.removeEventListener('focus', onAlphaPickerFocusIn, true); + element.removeEventListener('click', onAlphaPickerClick.bind(this)); + } + }; + + render(element, options); + + this.enabled(true); + this.visible(true); + } + + value(value, applyValue) { + const element = this.options.element; + let btn; + let selected; + + if (value !== undefined) { + if (value != null) { + value = value.toUpperCase(); + this._currentValue = value; + + if (this.options.mode !== 'keyboard') { + selected = element.querySelector(`.${selectedButtonClass}`); + + try { + btn = element.querySelector(`.alphaPickerButton[data-value='${value}']`); + } catch (err) { + console.error('error in querySelector:', err); + } + + if (btn && btn !== selected) { + btn.classList.add(selectedButtonClass); + } + if (selected && selected !== btn) { + selected.classList.remove(selectedButtonClass); + } } - if (selected && selected !== btn) { + } else { + this._currentValue = value; + + selected = element.querySelector(`.${selectedButtonClass}`); + if (selected) { selected.classList.remove(selectedButtonClass); } } - } else { - this._currentValue = value; - - selected = element.querySelector('.' + selectedButtonClass); - if (selected) { - selected.classList.remove(selectedButtonClass); - } } + + if (applyValue) { + element.dispatchEvent(new CustomEvent('alphavaluechanged', { + cancelable: false, + detail: { + value + } + })); + } + + return this._currentValue; } - if (applyValue) { - element.dispatchEvent(new CustomEvent('alphavaluechanged', { - cancelable: false, - detail: { - value: value - } - })); + on(name, fn) { + const element = this.options.element; + element.addEventListener(name, fn); } - return this._currentValue; - }; - - AlphaPicker.prototype.on = function (name, fn) { - var element = this.options.element; - element.addEventListener(name, fn); - }; - - AlphaPicker.prototype.off = function (name, fn) { - var element = this.options.element; - element.removeEventListener(name, fn); - }; - - AlphaPicker.prototype.visible = function (visible) { - - var element = this.options.element; - element.style.visibility = visible ? 'visible' : 'hidden'; - }; - - AlphaPicker.prototype.values = function () { - - var element = this.options.element; - var elems = element.querySelectorAll('.alphaPickerButton'); - var values = []; - for (var i = 0, length = elems.length; i < length; i++) { - - values.push(elems[i].getAttribute('data-value')); - + off(name, fn) { + const element = this.options.element; + element.removeEventListener(name, fn); } - return values; - }; + visible(visible) { + const element = this.options.element; + element.style.visibility = visible ? 'visible' : 'hidden'; + } - AlphaPicker.prototype.focus = function () { + values() { + const element = this.options.element; + const elems = element.querySelectorAll('.alphaPickerButton'); + const values = []; + for (let i = 0, length = elems.length; i < length; i++) { + values.push(elems[i].getAttribute('data-value')); + } - var element = this.options.element; - focusManager.autoFocus(element, true); - }; + return values; + } - AlphaPicker.prototype.destroy = function () { + focus() { + const element = this.options.element; + focusManager.autoFocus(element, true); + } - var element = this.options.element; - this.enabled(false); - element.classList.remove('focuscontainer-x'); - this.options = null; - }; + destroy() { + const element = this.options.element; + this.enabled(false); + element.classList.remove('focuscontainer-x'); + this.options = null; + } + } - return AlphaPicker; -}); +/* eslint-enable indent */ +export default AlphaPicker; diff --git a/src/components/appFooter/appFooter.js b/src/components/appFooter/appFooter.js index 033a0b008d..c60aa1a27c 100644 --- a/src/components/appFooter/appFooter.js +++ b/src/components/appFooter/appFooter.js @@ -1,17 +1,17 @@ -define(['browser', 'css!./appFooter'], function (browser) { - 'use strict'; +import 'css!./appFooter'; - function render(options) { - var elem = document.createElement('div'); - elem.classList.add('appfooter'); +function render(options) { + const elem = document.createElement('div'); + elem.classList.add('appfooter'); - document.body.appendChild(elem); + document.body.appendChild(elem); - return elem; - } + return elem; +} - function appFooter(options) { - var self = this; +class appFooter { + constructor(options) { + const self = this; self.element = render(options); self.add = function (elem) { @@ -26,12 +26,11 @@ define(['browser', 'css!./appFooter'], function (browser) { } }; } - - appFooter.prototype.destroy = function () { + destroy() { var self = this; self.element = null; - }; + } +} - return appFooter; -}); +export default appFooter; diff --git a/src/components/appRouter.js b/src/components/appRouter.js index 58c64e7d43..138d58e5c0 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -16,12 +16,12 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro show('/settings/settings.html'); }, showNowPlaying: function () { - show('/nowplaying.html'); + show('queue'); } }; function beginConnectionWizard() { - backdrop.clear(); + backdrop.clearBackdrop(); loading.show(); connectionManager.connect({ enableAutoLogin: appSettings.enableAutoLogin() @@ -53,7 +53,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro break; case 'ServerUpdateNeeded': require(['alert'], function (alert) { - alert({ + alert.default({ text: globalize.translate('ServerUpdateNeeded', 'https://github.com/jellyfin/jellyfin'), html: globalize.translate('ServerUpdateNeeded', 'https://github.com/jellyfin/jellyfin') }).then(function () { @@ -153,20 +153,14 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro }; if (!isBackNav) { - // Don't force a new view for home due to the back menu - //if (route.type !== 'home') { onNewViewNeeded(); return; - //} } viewManager.tryRestoreView(currentRequest, function () { - - // done currentRouteInfo = { route: route, path: ctx.path }; - }).catch(function (result) { if (!result || !result.cancelled) { onNewViewNeeded(); @@ -197,12 +191,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } function onRequestFail(e, data) { - var apiClient = this; if (data.status === 403) { if (data.errorCode === 'ParentalControl') { - var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true; // Bounce to the login screen, but not if a password entry fails, obviously @@ -210,7 +202,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater')); appRouter.showLocalLogin(apiClient.serverId()); } - } } } @@ -237,7 +228,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro if (navigator.connection) { var max = navigator.connection.downlinkMax; if (max && max > 0 && max < Number.POSITIVE_INFINITY) { - max /= 8; max *= 1000000; max *= 0.7; @@ -255,7 +245,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } function onApiClientCreated(e, newApiClient) { - newApiClient.normalizeImageOptions = normalizeImageOptions; if (browser.iOS) { @@ -269,12 +258,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } function initApiClient(apiClient) { - onApiClientCreated({}, apiClient); } function initApiClients() { - connectionManager.getApiClients().forEach(initApiClient); events.on(connectionManager, 'apiclientcreated', onApiClientCreated); @@ -290,7 +277,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro var firstConnectionResult; function start(options) { - loading.show(); initApiClients(); @@ -302,53 +288,29 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro enableAutoLogin: appSettings.enableAutoLogin() }).then(function (result) { - firstConnectionResult = result; options = options || {}; page({ click: options.click !== false, - hashbang: options.hashbang !== false, - enableHistory: enableHistory() + hashbang: options.hashbang !== false }); }).catch().then(function() { loading.hide(); }); } - function enableHistory() { - - //if (browser.edgeUwp) { - // return false; - //} - - // shows status bar on navigation - if (browser.xboxOne) { - return false; - } - - // Does not support history - if (browser.orsay) { - return false; - } - - return true; - } - function enableNativeHistory() { return false; } function authenticate(ctx, route, callback) { - var firstResult = firstConnectionResult; if (firstResult) { - firstConnectionResult = null; if (firstResult.State !== 'SignedIn' && !route.anonymous) { - handleConnectionResult(firstResult); return; } @@ -377,7 +339,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } if (apiClient && apiClient.isLoggedIn()) { - console.debug('appRouter - user is authenticated'); if (route.isDefaultRoute) { @@ -385,11 +346,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro loadUserSkinWithOptions(ctx); return; } else if (route.roles) { - validateRoles(apiClient, route.roles).then(function () { - callback(); - }, beginConnectionWizard); return; } @@ -431,8 +389,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro var isDummyBackToHome; function loadContent(ctx, route, html, request) { - - html = globalize.translateDocument(html, route.dictionary); + html = globalize.translateHtml(html, route.dictionary); request.view = html; viewManager.loadView(request); @@ -491,7 +448,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } function getWindowLocationSearch(win) { - var currentPath = currentRouteInfo ? (currentRouteInfo.path || '') : ''; var index = currentPath.indexOf('?'); @@ -535,9 +491,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) { return false; } - if (enableHistory()) { - return history.length > 1; - } + return (page.len || 0) > 0; } @@ -624,7 +578,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro } if (level === 'full' || level === 2) { - backdrop.clear(true); + backdrop.clearBackdrop(true); document.documentElement.classList.add('transparentDocument'); backgroundContainer.classList.add('backgroundContainer-transparent'); backdropContainer.classList.add('hide'); @@ -644,7 +598,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro function pushState(state, title, url) { state.navigate = false; history.pushState(state, title, url); - } function setBaseRoute() { diff --git a/src/components/apphost.js b/src/components/apphost.js index f200b9a642..e7d5bbc2f4 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -105,6 +105,8 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g deviceName = 'Sony PS4'; } else if (browser.chrome) { deviceName = 'Chrome'; + } else if (browser.edgeChromium) { + deviceName = 'Edge Chromium'; } else if (browser.edge) { deviceName = 'Edge'; } else if (browser.firefox) { @@ -257,12 +259,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g features.push('fullscreenchange'); } - if (browser.chrome || browser.edge && !browser.slow) { - if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) { - features.push('imageanalysis'); - } - } - if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) { features.push('physicalvolumecontrol'); } @@ -297,7 +293,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g features.push('fileinput'); } - if (browser.chrome) { + if (browser.chrome || browser.edgeChromium) { features.push('chromecast'); } @@ -353,7 +349,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g var deviceId; var deviceName; var appName = 'Jellyfin Web'; - var appVersion = '10.6.0'; + var appVersion = '10.7.0'; var appHost = { getWindowState: function () { diff --git a/src/components/backdrop/backdrop.js b/src/components/backdrop/backdrop.js index c15e35524c..d3c9e58b59 100644 --- a/src/components/backdrop/backdrop.js +++ b/src/components/backdrop/backdrop.js @@ -1,5 +1,11 @@ -define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) { - 'use strict'; +import browser from 'browser'; +import connectionManager from 'connectionManager'; +import playbackManager from 'playbackManager'; +import dom from 'dom'; +import * as userSettings from 'userSettings'; +import 'css!./backdrop'; + +/* eslint-disable indent */ function enableAnimation(elem) { if (browser.slow) { @@ -22,71 +28,70 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' return true; } - function Backdrop() { - } + class Backdrop { + load(url, parent, existingBackdropImage) { + const img = new Image(); + const self = this; - Backdrop.prototype.load = function (url, parent, existingBackdropImage) { - var img = new Image(); - var self = this; - - img.onload = function () { - if (self.isDestroyed) { - return; - } - - var backdropImage = document.createElement('div'); - backdropImage.classList.add('backdropImage'); - backdropImage.classList.add('displayingBackdropImage'); - backdropImage.style.backgroundImage = "url('" + url + "')"; - backdropImage.setAttribute('data-url', url); - - backdropImage.classList.add('backdropImageFadeIn'); - parent.appendChild(backdropImage); - - if (!enableAnimation(backdropImage)) { - if (existingBackdropImage && existingBackdropImage.parentNode) { - existingBackdropImage.parentNode.removeChild(existingBackdropImage); + img.onload = () => { + if (self.isDestroyed) { + return; } - internalBackdrop(true); - return; - } - var onAnimationComplete = function () { - dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, { + const backdropImage = document.createElement('div'); + backdropImage.classList.add('backdropImage'); + backdropImage.classList.add('displayingBackdropImage'); + backdropImage.style.backgroundImage = `url('${url}')`; + backdropImage.setAttribute('data-url', url); + + backdropImage.classList.add('backdropImageFadeIn'); + parent.appendChild(backdropImage); + + if (!enableAnimation(backdropImage)) { + if (existingBackdropImage && existingBackdropImage.parentNode) { + existingBackdropImage.parentNode.removeChild(existingBackdropImage); + } + internalBackdrop(true); + return; + } + + const onAnimationComplete = () => { + dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, { + once: true + }); + if (backdropImage === self.currentAnimatingElement) { + self.currentAnimatingElement = null; + } + if (existingBackdropImage && existingBackdropImage.parentNode) { + existingBackdropImage.parentNode.removeChild(existingBackdropImage); + } + }; + + dom.addEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, { once: true }); - if (backdropImage === self.currentAnimatingElement) { - self.currentAnimatingElement = null; - } - if (existingBackdropImage && existingBackdropImage.parentNode) { - existingBackdropImage.parentNode.removeChild(existingBackdropImage); - } + + internalBackdrop(true); }; - dom.addEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, { - once: true - }); - - internalBackdrop(true); - }; - - img.src = url; - }; - - Backdrop.prototype.cancelAnimation = function () { - var elem = this.currentAnimatingElement; - if (elem) { - elem.classList.remove('backdropImageFadeIn'); - this.currentAnimatingElement = null; + img.src = url; } - }; - Backdrop.prototype.destroy = function () { - this.isDestroyed = true; - this.cancelAnimation(); - }; + cancelAnimation() { + const elem = this.currentAnimatingElement; + if (elem) { + elem.classList.remove('backdropImageFadeIn'); + this.currentAnimatingElement = null; + } + } - var backdropContainer; + destroy() { + this.isDestroyed = true; + this.cancelAnimation(); + } + } + + let backdropContainer; function getBackdropContainer() { if (!backdropContainer) { backdropContainer = document.querySelector('.backdropContainer'); @@ -101,7 +106,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' return backdropContainer; } - function clearBackdrop(clearAll) { + export function clearBackdrop(clearAll) { clearRotation(); if (currentLoadingBackdrop) { @@ -109,7 +114,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' currentLoadingBackdrop = null; } - var elem = getBackdropContainer(); + const elem = getBackdropContainer(); elem.innerHTML = ''; if (clearAll) { @@ -119,7 +124,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' internalBackdrop(false); } - var backgroundContainer; + let backgroundContainer; function getBackgroundContainer() { if (!backgroundContainer) { backgroundContainer = document.querySelector('.backgroundContainer'); @@ -135,31 +140,27 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' } } - var hasInternalBackdrop; + let hasInternalBackdrop; function internalBackdrop(enabled) { hasInternalBackdrop = enabled; setBackgroundContainerBackgroundEnabled(); } - var hasExternalBackdrop; - function externalBackdrop(enabled) { + let hasExternalBackdrop; + export function externalBackdrop(enabled) { hasExternalBackdrop = enabled; setBackgroundContainerBackgroundEnabled(); } - function getRandom(min, max) { - return Math.floor(Math.random() * (max - min) + min); - } - - var currentLoadingBackdrop; + let currentLoadingBackdrop; function setBackdropImage(url) { if (currentLoadingBackdrop) { currentLoadingBackdrop.destroy(); currentLoadingBackdrop = null; } - var elem = getBackdropContainer(); - var existingBackdropImage = elem.querySelector('.displayingBackdropImage'); + const elem = getBackdropContainer(); + const existingBackdropImage = elem.querySelector('.displayingBackdropImage'); if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) { if (existingBackdropImage.getAttribute('data-url') === url) { @@ -168,7 +169,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' existingBackdropImage.classList.remove('displayingBackdropImage'); } - var instance = new Backdrop(); + const instance = new Backdrop(); instance.load(url, elem, existingBackdropImage); currentLoadingBackdrop = instance; } @@ -176,9 +177,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' function getItemImageUrls(item, imageOptions) { imageOptions = imageOptions || {}; - var apiClient = connectionManager.getApiClient(item.ServerId); + const apiClient = connectionManager.getApiClient(item.ServerId); if (item.BackdropImageTags && item.BackdropImageTags.length > 0) { - return item.BackdropImageTags.map(function (imgTag, index) { + return item.BackdropImageTags.map((imgTag, index) => { return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, { type: 'Backdrop', tag: imgTag, @@ -189,7 +190,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' } if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { - return item.ParentBackdropImageTags.map(function (imgTag, index) { + return item.ParentBackdropImageTags.map((imgTag, index) => { return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, { type: 'Backdrop', tag: imgTag, @@ -203,13 +204,13 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' } function getImageUrls(items, imageOptions) { - var list = []; - var onImg = function (img) { + const list = []; + const onImg = img => { list.push(img); }; - for (var i = 0, length = items.length; i < length; i++) { - var itemImages = getItemImageUrls(items[i], imageOptions); + for (let i = 0, length = items.length; i < length; i++) { + const itemImages = getItemImageUrls(items[i], imageOptions); itemImages.forEach(onImg); } @@ -229,7 +230,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' // If you don't care about the order of the elements inside // the array, you should sort both arrays here. - for (var i = 0; i < a.length; ++i) { + for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) { return false; } @@ -242,12 +243,12 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' return userSettings.enableBackdrops(); } - var rotationInterval; - var currentRotatingImages = []; - var currentRotationIndex = -1; - function setBackdrops(items, imageOptions, enableImageRotation) { + let rotationInterval; + let currentRotatingImages = []; + let currentRotationIndex = -1; + export function setBackdrops(items, imageOptions, enableImageRotation) { if (enabled()) { - var images = getImageUrls(items, imageOptions); + const images = getImageUrls(items, imageOptions); if (images.length) { startRotation(images, enableImageRotation); @@ -279,7 +280,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' return; } - var newIndex = currentRotationIndex + 1; + let newIndex = currentRotationIndex + 1; if (newIndex >= currentRotatingImages.length) { newIndex = 0; } @@ -289,7 +290,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' } function clearRotation() { - var interval = rotationInterval; + const interval = rotationInterval; if (interval) { clearInterval(interval); } @@ -299,7 +300,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' currentRotationIndex = -1; } - function setBackdrop(url, imageOptions) { + export function setBackdrop(url, imageOptions) { if (url && typeof url !== 'string') { url = getImageUrls([url], imageOptions)[0]; } @@ -312,10 +313,11 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings' } } - return { - setBackdrops: setBackdrops, - setBackdrop: setBackdrop, - clear: clearBackdrop, - externalBackdrop: externalBackdrop - }; -}); +/* eslint-enable indent */ + +export default { + setBackdrops: setBackdrops, + setBackdrop: setBackdrop, + clearBackdrop: clearBackdrop, + externalBackdrop: externalBackdrop +}; diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index d192bed7f0..edb9db28ba 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -291,12 +291,10 @@ import 'programStyles'; const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items); if (['auto', 'autohome', 'autooverflow', 'autoVertical'].includes(options.shape)) { - const requestedShape = options.shape; options.shape = null; if (primaryImageAspectRatio) { - if (primaryImageAspectRatio >= 3) { options.shape = 'banner'; options.coverImage = true; @@ -394,7 +392,6 @@ import 'programStyles'; } if (newIndexValue !== currentIndexValue) { - if (hasOpenRow) { html += '
'; hasOpenRow = false; @@ -402,7 +399,6 @@ import 'programStyles'; } if (hasOpenSection) { - html += '
'; if (isVertical) { @@ -426,7 +422,6 @@ import 'programStyles'; } if (options.rows && itemsInRow === 0) { - if (hasOpenRow) { html += '
'; hasOpenRow = false; @@ -686,7 +681,6 @@ import 'programStyles'; let valid = 0; for (let i = 0; i < lines.length; i++) { - let currentCssClass = cssClass; let text = lines[i]; @@ -713,7 +707,6 @@ import 'programStyles'; } if (forceLines) { - let linesLength = maxLines || Math.min(lines.length, maxLines || lines.length); while (valid < linesLength) { @@ -745,7 +738,6 @@ import 'programStyles'; let airTimeText = ''; if (item.StartDate) { - try { let date = datetime.parseISO8601Date(item.StartDate); @@ -792,7 +784,6 @@ import 'programStyles'; const showOtherText = isOuterFooter ? !overlayText : overlayText; if (isOuterFooter && options.cardLayout && layoutManager.mobile) { - if (options.cardFooterAside !== 'none') { html += ''; } @@ -807,9 +798,7 @@ import 'programStyles'; if (showOtherText) { if ((options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) { - if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) { - if (item.SeriesId) { lines.push(getTextActionButton({ Id: item.SeriesId, @@ -822,15 +811,12 @@ import 'programStyles'; lines.push(item.SeriesName); } } else { - if (isUsingLiveTvNaming(item)) { - lines.push(item.Name); if (!item.EpisodeTitle) { titleAdded = true; } - } else { const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''; @@ -848,7 +834,6 @@ import 'programStyles'; } if (showMediaTitle) { - const name = options.showTitle === 'auto' && !item.IsFolder && item.MediaType === 'Photo' ? '' : itemHelper.getDisplayName(item, { includeParentInfo: options.includeParentInfoInTitle }); @@ -865,7 +850,6 @@ import 'programStyles'; if (showOtherText) { if (options.showParentTitle && parentTitleUnderneath) { - if (isOuterFooter && item.AlbumArtists && item.AlbumArtists.length) { item.AlbumArtists[0].Type = 'MusicArtist'; item.AlbumArtists[0].IsFolder = true; @@ -899,7 +883,6 @@ import 'programStyles'; } if (options.showPremiereDate) { - if (item.PremiereDate) { try { lines.push(datetime.toLocaleDateString( @@ -908,7 +891,6 @@ import 'programStyles'; )); } catch (err) { lines.push(''); - } } else { lines.push(''); @@ -916,14 +898,10 @@ import 'programStyles'; } if (options.showYear || options.showSeriesYear) { - if (item.Type === 'Series') { if (item.Status === 'Continuing') { - lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || '')); - } else { - if (item.EndDate && item.ProductionYear) { const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear(); lines.push(item.ProductionYear + ((endYear === item.ProductionYear) ? '' : (' - ' + endYear))); @@ -937,9 +915,7 @@ import 'programStyles'; } if (options.showRuntime) { - if (item.RunTimeTicks) { - lines.push(datetime.getDisplayRunningTime(item.RunTimeTicks)); } else { lines.push(''); @@ -947,14 +923,11 @@ import 'programStyles'; } if (options.showAirTime) { - lines.push(getAirTimeText(item, options.showAirDateTime, options.showAirEndTime) || ''); } if (options.showChannelName) { - if (item.ChannelId) { - lines.push(getTextActionButton({ Id: item.ChannelId, @@ -971,7 +944,6 @@ import 'programStyles'; } if (options.showCurrentProgram && item.Type === 'TvChannel') { - if (item.CurrentProgram) { lines.push(item.CurrentProgram.Name); } else { @@ -980,7 +952,6 @@ import 'programStyles'; } if (options.showCurrentProgramTime && item.Type === 'TvChannel') { - if (item.CurrentProgram) { lines.push(getAirTimeText(item.CurrentProgram, false, true) || ''); } else { @@ -990,7 +961,6 @@ import 'programStyles'; if (options.showSeriesTimerTime) { if (item.RecordAnyTime) { - lines.push(globalize.translate('Anytime')); } else { lines.push(datetime.getDisplayTime(item.StartDate)); @@ -1025,7 +995,6 @@ import 'programStyles'; } if (html) { - if (!isOuterFooter || logoUrl || options.cardLayout) { html = '
' + html; @@ -1071,27 +1040,21 @@ import 'programStyles'; let childText; if (item.Type === 'Playlist') { - childText = ''; if (item.RunTimeTicks) { - let minutes = item.RunTimeTicks / 600000000; minutes = minutes || 1; childText += globalize.translate('ValueMinutes', Math.round(minutes)); - } else { childText += globalize.translate('ValueMinutes', 0); } counts.push(childText); - } else if (item.Type === 'Genre' || item.Type === 'Studio') { - if (item.MovieCount) { - childText = item.MovieCount === 1 ? globalize.translate('ValueOneMovie') : globalize.translate('ValueMovieCount', item.MovieCount); @@ -1100,7 +1063,6 @@ import 'programStyles'; } if (item.SeriesCount) { - childText = item.SeriesCount === 1 ? globalize.translate('ValueOneSeries') : globalize.translate('ValueSeriesCount', item.SeriesCount); @@ -1108,18 +1070,14 @@ import 'programStyles'; counts.push(childText); } if (item.EpisodeCount) { - childText = item.EpisodeCount === 1 ? globalize.translate('ValueOneEpisode') : globalize.translate('ValueEpisodeCount', item.EpisodeCount); counts.push(childText); } - } else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') { - if (item.AlbumCount) { - childText = item.AlbumCount === 1 ? globalize.translate('ValueOneAlbum') : globalize.translate('ValueAlbumCount', item.AlbumCount); @@ -1127,7 +1085,6 @@ import 'programStyles'; counts.push(childText); } if (item.SongCount) { - childText = item.SongCount === 1 ? globalize.translate('ValueOneSong') : globalize.translate('ValueSongCount', item.SongCount); @@ -1135,16 +1092,13 @@ import 'programStyles'; counts.push(childText); } if (item.MusicVideoCount) { - childText = item.MusicVideoCount === 1 ? globalize.translate('ValueOneMusicVideo') : globalize.translate('ValueMusicVideoCount', item.MusicVideoCount); counts.push(childText); } - } else if (item.Type === 'Series') { - childText = item.RecursiveItemCount === 1 ? globalize.translate('ValueOneEpisode') : globalize.translate('ValueEpisodeCount', item.RecursiveItemCount); @@ -1160,10 +1114,11 @@ import 'programStyles'; /** * Imports the refresh indicator element. */ - function requireRefreshIndicator() { + function importRefreshIndicator() { if (!refreshIndicatorLoaded) { refreshIndicatorLoaded = true; - require(['emby-itemrefreshindicator']); + /* eslint-disable-next-line no-unused-expressions */ + import('emby-itemrefreshindicator'); } } @@ -1197,13 +1152,11 @@ import 'programStyles'; let shape = options.shape; if (shape === 'mixed') { - shape = null; const primaryImageAspectRatio = item.PrimaryImageAspectRatio; if (primaryImageAspectRatio) { - if (primaryImageAspectRatio >= 1.33) { shape = 'mixedBackdrop'; } else if (primaryImageAspectRatio > 0.71) { @@ -1295,7 +1248,6 @@ import 'programStyles'; } if (overlayText) { - logoUrl = null; footerCssClass = progressHtml ? 'innerCardFooter fullInnerCardFooter' : 'innerCardFooter'; @@ -1404,7 +1356,6 @@ import 'programStyles'; indicatorsHtml += indicators.getTypeIndicator(item); if (options.showGroupCount) { - indicatorsHtml += indicators.getChildCountIndicatorHtml(item, { minCount: 1 }); @@ -1415,7 +1366,7 @@ import 'programStyles'; if (item.Type === 'CollectionFolder' || item.CollectionType) { const refreshClass = item.RefreshProgress ? '' : ' class="hide"'; indicatorsHtml += '
'; - requireRefreshIndicator(); + importRefreshIndicator(); } if (indicatorsHtml) { @@ -1498,15 +1449,16 @@ import 'programStyles'; const userData = item.UserData || {}; if (itemHelper.canMarkPlayed(item)) { - require(['emby-playstatebutton']); + /* eslint-disable-next-line no-unused-expressions */ + import('emby-playstatebutton'); html += ''; } if (itemHelper.canRate(item)) { - const likes = userData.Likes == null ? '' : userData.Likes; - require(['emby-ratingbutton']); + /* eslint-disable-next-line no-unused-expressions */ + import('emby-ratingbutton'); html += ''; } @@ -1583,7 +1535,6 @@ import 'programStyles'; const html = buildCardsHtmlInternal(items, options); if (html) { - if (options.itemsContainer.cardBuilderHtml !== html) { options.itemsContainer.innerHTML = html; @@ -1596,7 +1547,6 @@ import 'programStyles'; imageLoader.lazyChildren(options.itemsContainer); } else { - options.itemsContainer.innerHTML = html; options.itemsContainer.cardBuilderHtml = null; } @@ -1620,7 +1570,6 @@ import 'programStyles'; indicatorsElem = card.querySelector('.cardIndicators'); if (!indicatorsElem) { - const cardImageContainer = card.querySelector('.cardImageContainer'); indicatorsElem = document.createElement('div'); indicatorsElem.classList.add('cardIndicators'); @@ -1644,11 +1593,9 @@ import 'programStyles'; let itemProgressBar = null; if (userData.Played) { - playedIndicator = card.querySelector('.playedIndicator'); if (!playedIndicator) { - playedIndicator = document.createElement('div'); playedIndicator.classList.add('playedIndicator'); playedIndicator.classList.add('indicator'); @@ -1657,10 +1604,8 @@ import 'programStyles'; } playedIndicator.innerHTML = ''; } else { - playedIndicator = card.querySelector('.playedIndicator'); if (playedIndicator) { - playedIndicator.parentNode.removeChild(playedIndicator); } } @@ -1668,7 +1613,6 @@ import 'programStyles'; countIndicator = card.querySelector('.countIndicator'); if (!countIndicator) { - countIndicator = document.createElement('div'); countIndicator.classList.add('countIndicator'); indicatorsElem = ensureIndicators(card, indicatorsElem); @@ -1676,10 +1620,8 @@ import 'programStyles'; } countIndicator.innerHTML = userData.UnplayedItemCount; } else if (enableCountIndicator) { - countIndicator = card.querySelector('.countIndicator'); if (countIndicator) { - countIndicator.parentNode.removeChild(countIndicator); } } @@ -1691,7 +1633,6 @@ import 'programStyles'; }); if (progressHtml) { - itemProgressBar = card.querySelector('.itemProgressBar'); if (!itemProgressBar) { @@ -1710,7 +1651,6 @@ import 'programStyles'; itemProgressBar.innerHTML = progressHtml; } else { - itemProgressBar = card.querySelector('.itemProgressBar'); if (itemProgressBar) { itemProgressBar.parentNode.removeChild(itemProgressBar); diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index c6ee9ba3c5..0215f8d8e5 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -14,7 +14,6 @@ import browser from 'browser'; const enableFocusTransform = !browser.slow && !browser.edge; function buildChapterCardsHtml(item, chapters, options) { - // TODO move card creation code to Card component let className = 'card itemAction chapterCard'; @@ -35,7 +34,6 @@ import browser from 'browser'; let shape = (options.backdropShape || 'backdrop'); if (videoStream.Width && videoStream.Height) { - if ((videoStream.Width / videoStream.Height) <= 1.2) { shape = (options.squareShape || 'square'); } @@ -53,7 +51,6 @@ import browser from 'browser'; const apiClient = connectionManager.getApiClient(item.ServerId); for (let i = 0, length = chapters.length; i < length; i++) { - if (options.rows && itemsInRow === 0) { html += '
'; } @@ -73,9 +70,7 @@ import browser from 'browser'; } function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) { - if (ImageTag) { - return apiClient.getScaledImageUrl(Id, { maxWidth: maxWidth * 2, @@ -89,7 +84,6 @@ import browser from 'browser'; } function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) { - const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient); let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer'; @@ -116,7 +110,6 @@ import browser from 'browser'; } export function buildChapterCards(item, chapters, options) { - if (options.parentContainer) { // Abort if the container has been disposed if (!document.body.contains(options.parentContainer)) { diff --git a/src/components/cardbuilder/peoplecardbuilder.js b/src/components/cardbuilder/peoplecardbuilder.js index 3b9a26a704..5fc9e8ade5 100644 --- a/src/components/cardbuilder/peoplecardbuilder.js +++ b/src/components/cardbuilder/peoplecardbuilder.js @@ -8,7 +8,6 @@ import cardBuilder from 'cardBuilder'; export function buildPeopleCards(items, options) { - options = Object.assign(options || {}, { cardLayout: false, centerText: true, diff --git a/src/components/channelMapper/channelMapper.js b/src/components/channelMapper/channelMapper.js index f2ad88e713..89d085c185 100644 --- a/src/components/channelMapper/channelMapper.js +++ b/src/components/channelMapper/channelMapper.js @@ -1,10 +1,21 @@ -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'; +import dom from 'dom'; +import dialogHelper from 'dialogHelper'; +import loading from 'loading'; +import connectionManager from 'connectionManager'; +import globalize from 'globalize'; +import actionsheet from 'actionsheet'; +import 'emby-input'; +import 'paper-icon-button-light'; +import 'emby-button'; +import 'listViewStyle'; +import 'material-icons'; +import 'formDialogStyle'; - return function (options) { +export default class channelMapper { + constructor(options) { function mapChannel(button, channelId, providerChannelId) { loading.show(); - var providerId = options.providerId; + const providerId = options.providerId; connectionManager.getApiClient(options.serverId).ajax({ type: 'POST', url: ApiClient.getUrl('LiveTv/ChannelMappings'), @@ -14,8 +25,8 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act providerChannelId: providerChannelId }, dataType: 'json' - }).then(function (mapping) { - var listItem = dom.parentWithClass(button, 'listItem'); + }).then(mapping => { + const listItem = dom.parentWithClass(button, 'listItem'); button.setAttribute('data-providerid', mapping.ProviderChannelId); listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName); loading.hide(); @@ -23,42 +34,42 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act } function onChannelsElementClick(e) { - var btnMap = dom.parentWithClass(e.target, 'btnMap'); + const btnMap = dom.parentWithClass(e.target, 'btnMap'); if (btnMap) { - var channelId = btnMap.getAttribute('data-id'); - var providerChannelId = btnMap.getAttribute('data-providerid'); - var menuItems = currentMappingOptions.ProviderChannels.map(function (m) { + const channelId = btnMap.getAttribute('data-id'); + const providerChannelId = btnMap.getAttribute('data-providerid'); + const menuItems = currentMappingOptions.ProviderChannels.map(m => { return { name: m.Name, id: m.Id, selected: m.Id.toLowerCase() === providerChannelId.toLowerCase() }; - }).sort(function (a, b) { + }).sort((a, b) => { return a.name.localeCompare(b.name); }); actionsheet.show({ positionTo: btnMap, items: menuItems - }).then(function (newChannelId) { + }).then(newChannelId => { mapChannel(btnMap, channelId, newChannelId); }); } } function getChannelMappingOptions(serverId, providerId) { - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', { providerId: providerId })); } function getMappingSecondaryName(mapping, providerName) { - return (mapping.ProviderChannelName || '') + ' - ' + providerName; + return `${mapping.ProviderChannelName || ''} - ${providerName}`; } function getTunerChannelHtml(channel, providerName) { - var html = ''; + let html = ''; html += '
'; html += ''; html += '
'; @@ -73,16 +84,16 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act html += '
'; html += '
'; - html += ''; + html += ``; return html += '
'; } function getEditorHtml() { - var html = ''; + let html = ''; html += '
'; html += '
'; html += '
'; - html += '

' + globalize.translate('HeaderChannels') + '

'; + html += `

${globalize.translate('HeaderChannels')}

`; html += '
'; html += '
'; html += '
'; @@ -91,30 +102,29 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act } function initEditor(dlg, options) { - getChannelMappingOptions(options.serverId, options.providerId).then(function (result) { + getChannelMappingOptions(options.serverId, options.providerId).then(result => { currentMappingOptions = result; - var channelsElement = dlg.querySelector('.channels'); - channelsElement.innerHTML = result.TunerChannels.map(function (channel) { + const channelsElement = dlg.querySelector('.channels'); + channelsElement.innerHTML = result.TunerChannels.map(channel => { return getTunerChannelHtml(channel, result.ProviderName); }).join(''); channelsElement.addEventListener('click', onChannelsElementClick); }); } - var currentMappingOptions; - var self = this; + let currentMappingOptions; - self.show = function () { - var dialogOptions = { + this.show = () => { + const dialogOptions = { removeOnClose: true }; dialogOptions.size = 'small'; - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); dlg.classList.add('ui-body-a'); dlg.classList.add('background-theme-a'); - var html = ''; - var title = globalize.translate('MapChannels'); + let html = ''; + const title = globalize.translate('MapChannels'); html += '
'; html += ''; html += '

'; @@ -124,13 +134,13 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act html += getEditorHtml(); dlg.innerHTML = html; initEditor(dlg, options); - dlg.querySelector('.btnCancel').addEventListener('click', function () { + dlg.querySelector('.btnCancel').addEventListener('click', () => { dialogHelper.close(dlg); }); - return new Promise(function (resolve, reject) { + return new Promise(resolve => { dlg.addEventListener('close', resolve); dialogHelper.open(dlg); }); }; - }; -}); + } +} diff --git a/src/components/collectionEditor/collectionEditor.js b/src/components/collectionEditor/collectionEditor.js index 46b0640305..a115b86a8f 100644 --- a/src/components/collectionEditor/collectionEditor.js +++ b/src/components/collectionEditor/collectionEditor.js @@ -1,16 +1,31 @@ -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'; +import dom from 'dom'; +import dialogHelper from 'dialogHelper'; +import loading from 'loading'; +import layoutManager from 'layoutManager'; +import connectionManager from 'connectionManager'; +import appRouter from 'appRouter'; +import globalize from 'globalize'; +import 'emby-checkbox'; +import 'emby-input'; +import 'paper-icon-button-light'; +import 'emby-select'; +import 'material-icons'; +import 'css!./../formdialog'; +import 'emby-button'; +import 'flexStyles'; - var currentServerId; +/* eslint-disable indent */ + + let currentServerId; function onSubmit(e) { loading.show(); - var panel = dom.parentWithClass(this, 'dialog'); + const panel = dom.parentWithClass(this, 'dialog'); - var collectionId = panel.querySelector('#selectCollectionToAddTo').value; + const collectionId = panel.querySelector('#selectCollectionToAddTo').value; - var apiClient = connectionManager.getApiClient(currentServerId); + const apiClient = connectionManager.getApiClient(currentServerId); if (collectionId) { addToCollection(apiClient, panel, collectionId); @@ -23,8 +38,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } function createCollection(apiClient, dlg) { - - var url = apiClient.getUrl('Collections', { + const url = apiClient.getUrl('Collections', { Name: dlg.querySelector('#txtNewCollectionName').value, IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked, @@ -36,27 +50,23 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio url: url, dataType: 'json' - }).then(function (result) { - + }).then(result => { loading.hide(); - var id = result.Id; + const id = result.Id; dlg.submitted = true; dialogHelper.close(dlg); redirectToCollection(apiClient, id); - }); } function redirectToCollection(apiClient, id) { - appRouter.showItem(id, apiClient.serverId()); } function addToCollection(apiClient, dlg, id) { - - var url = apiClient.getUrl('Collections/' + id + '/Items', { + const url = apiClient.getUrl(`Collections/${id}/Items`, { Ids: dlg.querySelector('.fldSelectedItemIds').value || '' }); @@ -65,14 +75,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio type: 'POST', url: url - }).then(function () { - + }).then(() => { loading.hide(); dlg.submitted = true; dialogHelper.close(dlg); - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('MessageItemsAdded')); }); }); @@ -83,14 +92,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } function populateCollections(panel) { - loading.show(); - var select = panel.querySelector('#selectCollectionToAddTo'); + const select = panel.querySelector('#selectCollectionToAddTo'); panel.querySelector('.newCollectionInfo').classList.add('hide'); - var options = { + const options = { Recursive: true, IncludeItemTypes: 'BoxSet', @@ -98,16 +106,14 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio EnableTotalRecordCount: false }; - var apiClient = connectionManager.getApiClient(currentServerId); - apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) { + const apiClient = connectionManager.getApiClient(currentServerId); + apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => { + let html = ''; - var html = ''; + html += ``; - html += ''; - - html += result.Items.map(function (i) { - - return ''; + html += result.Items.map(i => { + return ``; }); select.innerHTML = html; @@ -119,8 +125,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } function getEditorHtml() { - - var html = ''; + let html = ''; html += '
'; html += '
'; @@ -134,27 +139,27 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio html += '
'; html += '
'; html += '
'; - html += ''; + html += ``; html += '
'; html += '
'; html += '
'; html += '
'; - html += ''; - html += '
' + globalize.translate('NewCollectionNameExample') + '
'; + html += ``; + html += `
${globalize.translate('NewCollectionNameExample')}
`; html += '
'; html += ''; // newCollectionInfo html += '
'; html += '
'; - html += ''; + html += ``; html += '
'; html += ''; @@ -167,7 +172,6 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } function initEditor(content, items) { - content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () { if (this.value) { content.querySelector('.newCollectionInfo').classList.add('hide'); @@ -188,7 +192,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } else { content.querySelector('.fldSelectCollection').classList.add('hide'); - var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo'); + const selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo'); selectCollectionToAddTo.innerHTML = ''; selectCollectionToAddTo.value = ''; triggerChange(selectCollectionToAddTo); @@ -196,79 +200,70 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio } function centerFocus(elem, horiz, on) { - require(['scrollHelper'], function (scrollHelper) { - var fn = on ? 'on' : 'off'; + import('scrollHelper').then(scrollHelper => { + const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); } - function CollectionEditor() { + export class showEditor { + constructor(options) { + const items = options.items || {}; + currentServerId = options.serverId; - } - - CollectionEditor.prototype.show = function (options) { - - var items = options.items || {}; - currentServerId = options.serverId; - - var dialogOptions = { - removeOnClose: true, - scrollY: false - }; - - if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; - } else { - dialogOptions.size = 'small'; - } - - var dlg = dialogHelper.createDialog(dialogOptions); - - dlg.classList.add('formDialog'); - - var html = ''; - var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection'); - - html += '
'; - html += ''; - html += '

'; - html += title; - html += '

'; - - if (appHost.supports('externallinks')) { - html += '' + globalize.translate('Help') + ''; - } - - html += '
'; - - html += getEditorHtml(); - - dlg.innerHTML = html; - - initEditor(dlg, items); - - dlg.querySelector('.btnCancel').addEventListener('click', function () { - - dialogHelper.close(dlg); - }); - - if (layoutManager.tv) { - centerFocus(dlg.querySelector('.formDialogContent'), false, true); - } - - return dialogHelper.open(dlg).then(function () { + const dialogOptions = { + removeOnClose: true, + scrollY: false + }; if (layoutManager.tv) { - centerFocus(dlg.querySelector('.formDialogContent'), false, false); + dialogOptions.size = 'fullscreen'; + } else { + dialogOptions.size = 'small'; } - if (dlg.submitted) { - return Promise.resolve(); + const dlg = dialogHelper.createDialog(dialogOptions); + + dlg.classList.add('formDialog'); + + let html = ''; + const title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection'); + + html += '
'; + html += ''; + html += '

'; + html += title; + html += '

'; + + html += '
'; + + html += getEditorHtml(); + + dlg.innerHTML = html; + + initEditor(dlg, items); + + dlg.querySelector('.btnCancel').addEventListener('click', () => { + dialogHelper.close(dlg); + }); + + if (layoutManager.tv) { + centerFocus(dlg.querySelector('.formDialogContent'), false, true); } - return Promise.reject(); - }); - }; + return dialogHelper.open(dlg).then(() => { + if (layoutManager.tv) { + centerFocus(dlg.querySelector('.formDialogContent'), false, false); + } - return CollectionEditor; -}); + if (dlg.submitted) { + return Promise.resolve(); + } + + return Promise.reject(); + }); + } + } + +/* eslint-enable indent */ +export default showEditor; diff --git a/src/components/confirm/confirm.js b/src/components/confirm/confirm.js index 517d6fa9be..0670816a53 100644 --- a/src/components/confirm/confirm.js +++ b/src/components/confirm/confirm.js @@ -1,13 +1,16 @@ -define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) { - 'use strict'; +import browser from 'browser'; +import dialog from 'dialog'; +import globalize from 'globalize'; +/* eslint-disable indent */ +export default (() => { function replaceAll(str, find, replace) { return str.split(find).join(replace); } if (browser.tv && window.confirm) { // Use the native confirm dialog - return function (options) { + return options => { if (typeof options === 'string') { options = { title: '', @@ -15,8 +18,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) }; } - var text = replaceAll(options.text || '', '
', '\n'); - var result = confirm(text); + const text = replaceAll(options.text || '', '
', '\n'); + const result = confirm(text); if (result) { return Promise.resolve(); @@ -26,8 +29,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) }; } else { // Use our own dialog - return function (text, title) { - var options; + return (text, title) => { + let options; if (typeof text === 'string') { options = { title: title, @@ -37,7 +40,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) options = text; } - var items = []; + const items = []; items.push({ name: options.cancelText || globalize.translate('ButtonCancel'), @@ -53,7 +56,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) options.buttons = items; - return dialog(options).then(function (result) { + return dialog.show(options).then(result => { if (result === 'ok') { return Promise.resolve(); } @@ -62,4 +65,5 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) }); }; } -}); +})(); +/* eslint-enable indent */ diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index cfb5821b38..1b13900d85 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -1,20 +1,30 @@ -define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import dom from 'dom'; +import layoutManager from 'layoutManager'; +import scrollHelper from 'scrollHelper'; +import globalize from 'globalize'; +import 'material-icons'; +import 'emby-button'; +import 'paper-icon-button-light'; +import 'emby-input'; +import 'formDialogStyle'; +import 'flexStyles'; + +/* eslint-disable indent */ function showDialog(options, template) { - - var dialogOptions = { + const dialogOptions = { removeOnClose: true, scrollY: false }; - var enableTvLayout = layoutManager.tv; + const enableTvLayout = layoutManager.tv; if (enableTvLayout) { dialogOptions.size = 'fullscreen'; } - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); @@ -22,7 +32,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're dlg.classList.add('align-items-center'); dlg.classList.add('justify-content-center'); - var formDialogContent = dlg.querySelector('.formDialogContent'); + const formDialogContent = dlg.querySelector('.formDialogContent'); formDialogContent.classList.add('no-grow'); if (enableTvLayout) { @@ -30,41 +40,36 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're formDialogContent.style['max-height'] = '60%'; scrollHelper.centerFocus.on(formDialogContent, false); } else { - formDialogContent.style.maxWidth = (Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px'; + formDialogContent.style.maxWidth = `${Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)}px`; dlg.classList.add('dialog-fullscreen-lowres'); } - //dlg.querySelector('.btnCancel').addEventListener('click', function (e) { - // dialogHelper.close(dlg); - //}); - if (options.title) { dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || ''; } else { dlg.querySelector('.formDialogHeaderTitle').classList.add('hide'); } - var displayText = options.html || options.text || ''; + const displayText = options.html || options.text || ''; dlg.querySelector('.text').innerHTML = displayText; if (!displayText) { dlg.querySelector('.dialogContentInner').classList.add('hide'); } - var i; - var length; - var html = ''; - var hasDescriptions = false; + let i; + let length; + let html = ''; + let hasDescriptions = false; for (i = 0, length = options.buttons.length; i < length; i++) { + const item = options.buttons[i]; + const autoFocus = i === 0 ? ' autofocus' : ''; - var item = options.buttons[i]; - var autoFocus = i === 0 ? ' autofocus' : ''; - - var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize'; + let buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize'; if (item.type) { - buttonClass += ' button-' + item.type; + buttonClass += ` button-${item.type}`; } if (item.description) { @@ -75,10 +80,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom'; } - html += ''; + html += ``; if (item.description) { - html += '
' + item.description + '
'; + html += `
${item.description}
`; } } @@ -88,19 +93,18 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical'); } - var dialogResult; + let dialogResult; function onButtonClick() { dialogResult = this.getAttribute('data-id'); dialogHelper.close(dlg); } - var buttons = dlg.querySelectorAll('.btnOption'); + const buttons = dlg.querySelectorAll('.btnOption'); for (i = 0, length = buttons.length; i < length; i++) { buttons[i].addEventListener('click', onButtonClick); } - return dialogHelper.open(dlg).then(function () { - + return dialogHelper.open(dlg).then(() => { if (enableTvLayout) { scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); } @@ -113,9 +117,8 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're }); } - return function (text, title) { - - var options; + export async function show(text, title) { + let options; if (typeof text === 'string') { options = { title: title, @@ -125,10 +128,13 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're options = text; } - return new Promise(function (resolve, reject) { - require(['text!./dialog.template.html'], function (template) { - showDialog(options, template).then(resolve, reject); - }); + const { default: template } = await import('text!./dialog.template.html'); + return new Promise((resolve, reject) => { + showDialog(options, template).then(resolve, reject); }); - }; -}); + } + +/* eslint-enable indent */ +export default { + show: show +}; diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index 8b08cde678..1f11d8a195 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -1,10 +1,17 @@ -define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) { - 'use strict'; +import appRouter from 'appRouter'; +import focusManager from 'focusManager'; +import browser from 'browser'; +import layoutManager from 'layoutManager'; +import inputManager from 'inputManager'; +import dom from 'dom'; +import 'css!./dialoghelper.css'; +import 'scrollStyles'; - var globalOnOpenCallback; +/* eslint-disable indent */ + + let globalOnOpenCallback; function enableAnimation() { - // too slow if (browser.tv) { return false; @@ -14,7 +21,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function removeCenterFocus(dlg) { - if (layoutManager.tv) { if (dlg.classList.contains('scrollX')) { centerFocus(dlg, true, false); @@ -25,9 +31,8 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function tryRemoveElement(elem) { - var parentNode = elem.parentNode; + const parentNode = elem.parentNode; if (parentNode) { - // Seeing crashes in edge webview try { parentNode.removeChild(elem); @@ -38,15 +43,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function DialogHashHandler(dlg, hash, resolve) { - - var self = this; + const self = this; self.originalUrl = window.location.href; - var activeElement = document.activeElement; - var removeScrollLockOnClose = false; + const activeElement = document.activeElement; + let removeScrollLockOnClose = false; function onHashChange(e) { - - var isBack = self.originalUrl === window.location.href; + const isBack = self.originalUrl === window.location.href; if (isBack || !isOpened(dlg)) { window.removeEventListener('popstate', onHashChange); @@ -59,7 +62,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function onBackCommand(e) { - if (e.detail.command === 'back') { self.closedByBack = true; e.preventDefault(); @@ -69,7 +71,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function onDialogClosed() { - if (!isHistoryEnabled(dlg)) { inputManager.off(dlg, onBackCommand); } @@ -84,7 +85,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } if (!self.closedByBack && isHistoryEnabled(dlg)) { - var state = history.state || {}; + const state = history.state || {}; if (state.dialogId === hash) { history.back(); } @@ -97,7 +98,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', if (dlg.getAttribute('data-removeonclose') !== 'false') { removeCenterFocus(dlg); - var dialogContainer = dlg.dialogContainer; + const dialogContainer = dlg.dialogContainer; if (dialogContainer) { tryRemoveElement(dialogContainer); dlg.dialogContainer = null; @@ -108,7 +109,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', //resolve(); // if we just called history.back(), then use a timeout to allow the history events to fire first - setTimeout(function () { + setTimeout(() => { resolve({ element: dlg, closedByBack: self.closedByBack @@ -118,7 +119,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', dlg.addEventListener('close', onDialogClosed); - var center = !dlg.classList.contains('dialog-fixedSize'); + const center = !dlg.classList.contains('dialog-fixedSize'); if (center) { dlg.classList.add('centeredDialog'); } @@ -141,7 +142,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', animateDialogOpen(dlg); if (isHistoryEnabled(dlg)) { - appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash); + appRouter.pushState({ dialogId: hash }, 'Dialog', `#${hash}`); window.addEventListener('popstate', onHashChange); } else { @@ -150,11 +151,10 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function addBackdropOverlay(dlg) { - - var backdrop = document.createElement('div'); + const backdrop = document.createElement('div'); backdrop.classList.add('dialogBackdrop'); - var backdropParent = dlg.dialogContainer || dlg; + const backdropParent = dlg.dialogContainer || dlg; backdropParent.parentNode.insertBefore(backdrop, backdropParent); dlg.backdrop = backdrop; @@ -162,7 +162,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', void backdrop.offsetWidth; backdrop.classList.add('dialogBackdropOpened'); - dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) { + dom.addEventListener((dlg.dialogContainer || backdrop), 'click', e => { if (e.target === dlg.dialogContainer) { close(dlg); } @@ -170,7 +170,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', passive: true }); - dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) { + dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', e => { if (e.target === dlg.dialogContainer) { // Close the application dialog menu close(dlg); @@ -184,37 +184,33 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', return dlg.getAttribute('data-history') === 'true'; } - function open(dlg) { - + export function open(dlg) { if (globalOnOpenCallback) { globalOnOpenCallback(dlg); } - var parent = dlg.parentNode; + const parent = dlg.parentNode; if (parent) { parent.removeChild(dlg); } - var dialogContainer = document.createElement('div'); + const dialogContainer = document.createElement('div'); dialogContainer.classList.add('dialogContainer'); dialogContainer.appendChild(dlg); dlg.dialogContainer = dialogContainer; document.body.appendChild(dialogContainer); - return new Promise(function (resolve, reject) { - - new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve); + return new Promise((resolve, reject) => { + new DialogHashHandler(dlg, `dlg${new Date().getTime()}`, resolve); }); } function isOpened(dlg) { - //return dlg.opened; return !dlg.classList.contains('hide'); } - function close(dlg) { - + export function close(dlg) { if (isOpened(dlg)) { if (isHistoryEnabled(dlg)) { history.back(); @@ -225,15 +221,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function closeDialog(dlg) { - if (!dlg.classList.contains('hide')) { - dlg.dispatchEvent(new CustomEvent('closing', { bubbles: false, cancelable: false })); - var onAnimationFinish = function () { + const onAnimationFinish = () => { focusManager.popScope(dlg); dlg.classList.add('hide'); @@ -248,8 +242,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function animateDialogOpen(dlg) { - - var onAnimationFinish = function () { + const onAnimationFinish = () => { focusManager.pushScope(dlg); if (dlg.getAttribute('data-autofocus') === 'true') { @@ -263,8 +256,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', }; if (enableAnimation()) { - - var onFinish = function () { + const onFinish = () => { dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { once: true }); @@ -280,27 +272,24 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function animateDialogClose(dlg, onAnimationFinish) { - if (enableAnimation()) { - - var animated = true; + let animated = true; switch (dlg.animationConfig.exit.name) { - case 'fadeout': - dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + dlg.style.animation = `fadeout ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`; break; case 'scaledown': - dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + dlg.style.animation = `scaledown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`; break; case 'slidedown': - dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; + dlg.style.animation = `slidedown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`; break; default: animated = false; break; } - var onFinish = function () { + const onFinish = () => { dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { once: true }); @@ -318,10 +307,9 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', onAnimationFinish(); } - var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style; + const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style; function shouldLockDocumentScroll(options) { - if (supportsOverscrollBehavior && (options.size || !browser.touch)) { return false; } @@ -342,8 +330,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function removeBackdrop(dlg) { - - var backdrop = dlg.backdrop; + const backdrop = dlg.backdrop; if (!backdrop) { return; @@ -351,12 +338,11 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', dlg.backdrop = null; - var onAnimationFinish = function () { + const onAnimationFinish = () => { tryRemoveElement(backdrop); }; if (enableAnimation()) { - backdrop.classList.remove('dialogBackdropOpened'); // this is not firing animatonend @@ -368,20 +354,19 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', } function centerFocus(elem, horiz, on) { - require(['scrollHelper'], function (scrollHelper) { - var fn = on ? 'on' : 'off'; + import('scrollHelper').then(scrollHelper => { + const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); } - function createDialog(options) { - + export function createDialog(options) { options = options || {}; // If there's no native dialog support, use a plain div // Also not working well in samsung tizen browser, content inside not clickable // Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog - var dlg = document.createElement('div'); + const dlg = document.createElement('div'); dlg.classList.add('focuscontainer'); dlg.classList.add('hide'); @@ -406,17 +391,17 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', dlg.setAttribute('data-autofocus', 'true'); } - var defaultEntryAnimation; - var defaultExitAnimation; + let defaultEntryAnimation; + let defaultExitAnimation; defaultEntryAnimation = 'scaleup'; defaultExitAnimation = 'scaledown'; - var entryAnimation = options.entryAnimation || defaultEntryAnimation; - var exitAnimation = options.exitAnimation || defaultExitAnimation; + const entryAnimation = options.entryAnimation || defaultEntryAnimation; + const exitAnimation = options.exitAnimation || defaultExitAnimation; // If it's not fullscreen then lower the default animation speed to make it open really fast - var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280); - var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220); + const entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280); + const exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220); dlg.animationConfig = { // scale up @@ -461,24 +446,22 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', if (options.size) { dlg.classList.add('dialog-fixedSize'); - dlg.classList.add('dialog-' + options.size); + dlg.classList.add(`dialog-${options.size}`); } if (enableAnimation()) { - switch (dlg.animationConfig.entry.name) { - case 'fadein': - dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal'; + dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`; break; case 'scaleup': - dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both'; + dlg.style.animation = `scaleup ${entryAnimationDuration}ms ease-out normal both`; break; case 'slideup': - dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal'; + dlg.style.animation = `slideup ${entryAnimationDuration}ms ease-out normal`; break; case 'slidedown': - dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal'; + dlg.style.animation = `slidedown ${entryAnimationDuration}ms ease-out normal`; break; default: break; @@ -488,12 +471,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', return dlg; } - return { - open: open, - close: close, - createDialog: createDialog, - setOnOpen: function (val) { - globalOnOpenCallback = val; - } - }; -}); + export function setOnOpen(val) { + globalOnOpenCallback = val; + } + +/* eslint-enable indent */ + +export default { + open: open, + close: close, + createDialog: createDialog, + setOnOpen: setOnOpen +}; diff --git a/src/components/directorybrowser/directorybrowser.js b/src/components/directorybrowser/directorybrowser.js index e08fcc8336..41744bdcbb 100644 --- a/src/components/directorybrowser/directorybrowser.js +++ b/src/components/directorybrowser/directorybrowser.js @@ -1,9 +1,19 @@ -define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) { - 'use strict'; +import loading from 'loading'; +import dialogHelper from 'dialogHelper'; +import dom from 'dom'; +import globalize from 'globalize'; +import 'listViewStyle'; +import 'emby-input'; +import 'paper-icon-button-light'; +import 'css!./directorybrowser'; +import 'formDialogStyle'; +import 'emby-button'; + +/* eslint-disable indent */ function getSystemInfo() { return systemInfo ? Promise.resolve(systemInfo) : ApiClient.getPublicSystemInfo().then( - function(info) { + info => { systemInfo = info; return info; } @@ -21,9 +31,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in loading.show(); - var promises = []; + const promises = []; - if ('Network' === path) { + if (path === 'Network') { promises.push(ApiClient.getNetworkDevices()); } else { if (path) { @@ -35,10 +45,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } Promise.all(promises).then( - function(responses) { - var folders = responses[0]; - var parentPath = responses[1] || ''; - var html = ''; + responses => { + const folders = responses[0]; + const parentPath = responses[1] || ''; + let html = ''; page.querySelector('.results').scrollTop = 0; page.querySelector('#txtDirectoryPickerPath').value = path || ''; @@ -46,9 +56,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in if (path) { html += getItem('lnkPath lnkDirectory', '', parentPath, '...'); } - for (var i = 0, length = folders.length; i < length; i++) { - var folder = folders[i]; - var cssClass = 'File' === folder.Type ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory'; + for (let i = 0, length = folders.length; i < length; i++) { + const folder = folders[i]; + const cssClass = folder.Type === 'File' ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory'; html += getItem(cssClass, folder.Type, folder.Path, folder.Name); } @@ -58,7 +68,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in page.querySelector('.results').innerHTML = html; loading.hide(); - }, function() { + }, () => { if (updatePathOnError) { page.querySelector('#txtDirectoryPickerPath').value = ''; page.querySelector('.results').innerHTML = ''; @@ -69,8 +79,8 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } function getItem(cssClass, type, path, name) { - var html = ''; - html += '
'; + let html = ''; + html += `
`; html += '
'; html += '
'; html += name; @@ -82,19 +92,19 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } function getEditorHtml(options, systemInfo) { - var html = ''; + let html = ''; html += '
'; html += '
'; if (!options.pathReadOnly) { - var instruction = options.instruction ? options.instruction + '

' : ''; + const instruction = options.instruction ? `${options.instruction}

` : ''; html += '
'; html += instruction; - if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) { + if (systemInfo.OperatingSystem.toLowerCase() === 'bsd') { html += '
'; html += '
'; html += globalize.translate('MessageDirectoryPickerBSDInstruction'); html += '
'; - } else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) { + } else if (systemInfo.OperatingSystem.toLowerCase() === 'linux') { html += '
'; html += '
'; html += globalize.translate('MessageDirectoryPickerLinuxInstruction'); @@ -105,17 +115,17 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in html += '
'; html += '
'; html += '
'; - var labelKey; + let labelKey; if (options.includeFiles !== true) { labelKey = 'LabelFolder'; } else { labelKey = 'LabelPath'; } - var readOnlyAttribute = options.pathReadOnly ? ' readonly' : ''; - html += ''; + const readOnlyAttribute = options.pathReadOnly ? ' readonly' : ''; + html += ``; html += '
'; if (!readOnlyAttribute) { - html += ''; + html += ``; } html += '
'; if (!readOnlyAttribute) { @@ -123,14 +133,14 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } if (options.enableNetworkSharePath) { html += '
'; - html += ''; + html += ``; html += '
'; html += globalize.translate('LabelOptionalNetworkPathHelp', '\\\\server', '\\\\192.168.1.101'); html += '
'; html += '
'; } html += '
'; - html += ''; + html += ``; html += '
'; html += '
'; html += '
'; @@ -147,7 +157,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } function alertTextWithOptions(options) { - require(['alert'], function(alert) { + import('alert').then(({default: alert}) => { alert(options); }); } @@ -160,7 +170,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in ValidateWriteable: validateWriteable, Path: path } - }).catch(function(response) { + }).catch(response => { if (response) { if (response.status === 404) { alertText(globalize.translate('PathNotFound')); @@ -180,10 +190,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } function initEditor(content, options, fileOptions) { - content.addEventListener('click', function(e) { - var lnkPath = dom.parentWithClass(e.target, 'lnkPath'); + content.addEventListener('click', e => { + const lnkPath = dom.parentWithClass(e.target, 'lnkPath'); if (lnkPath) { - var path = lnkPath.getAttribute('data-path'); + const path = lnkPath.getAttribute('data-path'); if (lnkPath.classList.contains('lnkFile')) { content.querySelector('#txtDirectoryPickerPath').value = path; } else { @@ -192,25 +202,25 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in } }); - content.addEventListener('click', function(e) { + content.addEventListener('click', e => { if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) { - var path = content.querySelector('#txtDirectoryPickerPath').value; + const path = content.querySelector('#txtDirectoryPickerPath').value; refreshDirectoryBrowser(content, path, fileOptions); } }); - content.addEventListener('change', function(e) { - var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT'); - if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) { + content.addEventListener('change', e => { + const txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT'); + if (txtDirectoryPickerPath && txtDirectoryPickerPath.id === 'txtDirectoryPickerPath') { refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions); } }); content.querySelector('form').addEventListener('submit', function(e) { if (options.callback) { - var networkSharePath = this.querySelector('#txtNetworkPath'); + let networkSharePath = this.querySelector('#txtNetworkPath'); networkSharePath = networkSharePath ? networkSharePath.value : null; - var path = this.querySelector('#txtDirectoryPickerPath').value; + const path = this.querySelector('#txtDirectoryPickerPath').value; validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath)); } e.preventDefault(); @@ -224,77 +234,79 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in return Promise.resolve(options.path); } else { return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then( - function(result) { + result => { return result.Path || ''; - }, function() { + }, () => { return ''; } ); } } - function directoryBrowser() { - var currentDialog; - var self = this; - self.show = function(options) { - options = options || {}; - var fileOptions = { - includeDirectories: true - }; - if (options.includeDirectories != null) { - fileOptions.includeDirectories = options.includeDirectories; - } - if (options.includeFiles != null) { - fileOptions.includeFiles = options.includeFiles; - } - Promise.all([getSystemInfo(), getDefaultPath(options)]).then( - function(responses) { - var systemInfo = responses[0]; - var initialPath = responses[1]; - var dlg = dialogHelper.createDialog({ - size: 'small', - removeOnClose: true, - scrollY: false - }); - dlg.classList.add('ui-body-a'); - dlg.classList.add('background-theme-a'); - dlg.classList.add('directoryPicker'); - dlg.classList.add('formDialog'); - - var html = ''; - html += '
'; - html += ''; - html += '

'; - html += options.header || globalize.translate('HeaderSelectPath'); - html += '

'; - html += '
'; - html += getEditorHtml(options, systemInfo); - dlg.innerHTML = html; - initEditor(dlg, options, fileOptions); - dlg.addEventListener('close', onDialogClosed); - dialogHelper.open(dlg); - dlg.querySelector('.btnCloseDialog').addEventListener('click', function() { - dialogHelper.close(dlg); - }); - currentDialog = dlg; - dlg.querySelector('#txtDirectoryPickerPath').value = initialPath; - var txtNetworkPath = dlg.querySelector('#txtNetworkPath'); - if (txtNetworkPath) { - txtNetworkPath.value = options.networkSharePath || ''; - } - if (!options.pathReadOnly) { - refreshDirectoryBrowser(dlg, initialPath, fileOptions, true); - } + class directoryBrowser { + constructor() { + let currentDialog; + this.show = options => { + options = options || {}; + const fileOptions = { + includeDirectories: true + }; + if (options.includeDirectories != null) { + fileOptions.includeDirectories = options.includeDirectories; } - ); - }; - self.close = function() { - if (currentDialog) { - dialogHelper.close(currentDialog); - } - }; + if (options.includeFiles != null) { + fileOptions.includeFiles = options.includeFiles; + } + Promise.all([getSystemInfo(), getDefaultPath(options)]).then( + responses => { + const systemInfo = responses[0]; + const initialPath = responses[1]; + const dlg = dialogHelper.createDialog({ + size: 'small', + removeOnClose: true, + scrollY: false + }); + dlg.classList.add('ui-body-a'); + dlg.classList.add('background-theme-a'); + dlg.classList.add('directoryPicker'); + dlg.classList.add('formDialog'); + + let html = ''; + html += '
'; + html += ''; + html += '

'; + html += options.header || globalize.translate('HeaderSelectPath'); + html += '

'; + html += '
'; + html += getEditorHtml(options, systemInfo); + dlg.innerHTML = html; + initEditor(dlg, options, fileOptions); + dlg.addEventListener('close', onDialogClosed); + dialogHelper.open(dlg); + dlg.querySelector('.btnCloseDialog').addEventListener('click', () => { + dialogHelper.close(dlg); + }); + currentDialog = dlg; + dlg.querySelector('#txtDirectoryPickerPath').value = initialPath; + const txtNetworkPath = dlg.querySelector('#txtNetworkPath'); + if (txtNetworkPath) { + txtNetworkPath.value = options.networkSharePath || ''; + } + if (!options.pathReadOnly) { + refreshDirectoryBrowser(dlg, initialPath, fileOptions, true); + } + } + ); + }; + this.close = () => { + if (currentDialog) { + dialogHelper.close(currentDialog); + } + }; + } } - var systemInfo; - return directoryBrowser; -}); + let systemInfo; + +/* eslint-enable indent */ +export default directoryBrowser; diff --git a/src/components/displaySettings/displaySettings.js b/src/components/displaySettings/displaySettings.js index c4eb35f49f..ba78ab99e1 100644 --- a/src/components/displaySettings/displaySettings.js +++ b/src/components/displaySettings/displaySettings.js @@ -1,22 +1,37 @@ -define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) { - 'use strict'; +import browser from 'browser'; +import layoutManager from 'layoutManager'; +import appSettings from 'appSettings'; +import pluginManager from 'pluginManager'; +import appHost from 'apphost'; +import focusManager from 'focusManager'; +import datetime from 'datetime'; +import globalize from 'globalize'; +import loading from 'loading'; +import connectionManager from 'connectionManager'; +import skinManager from 'skinManager'; +import events from 'events'; +import 'emby-select'; +import 'emby-checkbox'; +import 'emby-button'; + +/* eslint-disable indent */ function fillThemes(select, isDashboard) { - select.innerHTML = skinManager.getThemes().map(function (t) { - var value = t.id; + select.innerHTML = skinManager.getThemes().map(t => { + let value = t.id; if (t.isDefault && !isDashboard) { value = ''; } else if (t.isDefaultServerDashboard && isDashboard) { value = ''; } - return ''; + return ``; }).join(''); } function loadScreensavers(context, userSettings) { - var selectScreensaver = context.querySelector('.selectScreensaver'); - var options = pluginManager.ofType('screensaver').map(function (plugin) { + const selectScreensaver = context.querySelector('.selectScreensaver'); + const options = pluginManager.ofType('screensaver').map(plugin => { return { name: plugin.name, value: plugin.id @@ -28,8 +43,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' value: 'none' }); - selectScreensaver.innerHTML = options.map(function (o) { - return ''; + selectScreensaver.innerHTML = options.map(o => { + return ``; }).join(''); selectScreensaver.value = userSettings.screensaver(); @@ -40,9 +55,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' } function loadSoundEffects(context, userSettings) { - - var selectSoundEffects = context.querySelector('.selectSoundEffects'); - var options = pluginManager.ofType('soundeffects').map(function (plugin) { + const selectSoundEffects = context.querySelector('.selectSoundEffects'); + const options = pluginManager.ofType('soundeffects').map(plugin => { return { name: plugin.name, value: plugin.id @@ -54,8 +68,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' value: 'none' }); - selectSoundEffects.innerHTML = options.map(function (o) { - return ''; + selectSoundEffects.innerHTML = options.map(o => { + return ``; }).join(''); selectSoundEffects.value = userSettings.soundEffects(); @@ -66,18 +80,17 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' } function loadSkins(context, userSettings) { + const selectSkin = context.querySelector('.selectSkin'); - var selectSkin = context.querySelector('.selectSkin'); - - var options = pluginManager.ofType('skin').map(function (plugin) { + const options = pluginManager.ofType('skin').map(plugin => { return { name: plugin.name, value: plugin.id }; }); - selectSkin.innerHTML = options.map(function (o) { - return ''; + selectSkin.innerHTML = options.map(o => { + return ``; }).join(''); selectSkin.value = userSettings.skin(); @@ -92,8 +105,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' } } - function showOrHideMissingEpisodesField(context, user, apiClient) { - + function showOrHideMissingEpisodesField(context) { if (browser.tizen || browser.web0s) { context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide'); return; @@ -102,11 +114,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' context.querySelector('.fldDisplayMissingEpisodes').classList.remove('hide'); } - function loadForm(context, user, userSettings, apiClient) { - - var loggedInUserId = apiClient.getCurrentUserId(); - var userId = user.Id; - + function loadForm(context, user, userSettings) { if (user.Policy.IsAdministrator) { context.querySelector('.selectDashboardThemeContainer').classList.remove('hide'); } else { @@ -167,8 +175,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' context.querySelector('.chkRunAtStartup').checked = appSettings.runAtStartup(); - var selectTheme = context.querySelector('#selectTheme'); - var selectDashboardTheme = context.querySelector('#selectDashboardTheme'); + const selectTheme = context.querySelector('#selectTheme'); + const selectDashboardTheme = context.querySelector('#selectDashboardTheme'); fillThemes(selectTheme); fillThemes(selectDashboardTheme, true); @@ -195,13 +203,12 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || ''; - showOrHideMissingEpisodesField(context, user, apiClient); + showOrHideMissingEpisodesField(context); loading.hide(); } function saveUser(context, user, userSettingsInstance, apiClient) { - appSettings.runAtStartup(context.querySelector('.chkRunAtStartup').checked); user.Configuration.DisplayMissingEpisodes = context.querySelector('.chkDisplayMissingEpisodes').checked; @@ -239,29 +246,29 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) { loading.show(); - apiClient.getUser(userId).then(function (user) { - saveUser(context, user, userSettings, apiClient).then(function () { + apiClient.getUser(userId).then(user => { + saveUser(context, user, userSettings, apiClient).then(() => { loading.hide(); if (enableSaveConfirmation) { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('SettingsSaved')); }); } events.trigger(instance, 'saved'); - }, function () { + }, () => { loading.hide(); }); }); } function onSubmit(e) { - var self = this; - var apiClient = connectionManager.getApiClient(self.options.serverId); - var userId = self.options.userId; - var userSettings = self.options.userSettings; + const self = this; + const apiClient = connectionManager.getApiClient(self.options.serverId); + const userId = self.options.userId; + const userSettings = self.options.userSettings; - userSettings.setUserInfo(userId, apiClient).then(function () { - var enableSaveConfirmation = self.options.enableSaveConfirmation; + userSettings.setUserInfo(userId, apiClient).then(() => { + const enableSaveConfirmation = self.options.enableSaveConfirmation; save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation); }); @@ -272,50 +279,51 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', ' return false; } - function embed(options, self) { - require(['text!./displaySettings.template.html'], function (template) { - options.element.innerHTML = globalize.translateDocument(template, 'core'); - options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); - if (options.enableSaveButton) { - options.element.querySelector('.btnSave').classList.remove('hide'); - } - self.loadData(options.autoFocus); - }); + async function embed(options, self) { + const { default: template } = await import('text!./displaySettings.template.html'); + options.element.innerHTML = globalize.translateHtml(template, 'core'); + options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); + if (options.enableSaveButton) { + options.element.querySelector('.btnSave').classList.remove('hide'); + } + self.loadData(options.autoFocus); } - function DisplaySettings(options) { - this.options = options; - embed(options, this); - } + class DisplaySettings { + constructor(options) { + this.options = options; + embed(options, this); + } - DisplaySettings.prototype.loadData = function (autoFocus) { - var self = this; - var context = self.options.element; + loadData(autoFocus) { + const self = this; + const context = self.options.element; - loading.show(); + loading.show(); - var userId = self.options.userId; - var apiClient = connectionManager.getApiClient(self.options.serverId); - var userSettings = self.options.userSettings; + const userId = self.options.userId; + const apiClient = connectionManager.getApiClient(self.options.serverId); + const userSettings = self.options.userSettings; - return apiClient.getUser(userId).then(function (user) { - return userSettings.setUserInfo(userId, apiClient).then(function () { - self.dataLoaded = true; - loadForm(context, user, userSettings, apiClient); - if (autoFocus) { - focusManager.autoFocus(context); - } + return apiClient.getUser(userId).then(user => { + return userSettings.setUserInfo(userId, apiClient).then(() => { + self.dataLoaded = true; + loadForm(context, user, userSettings); + if (autoFocus) { + focusManager.autoFocus(context); + } + }); }); - }); - }; + } - DisplaySettings.prototype.submit = function () { - onSubmit.call(this); - }; + submit() { + onSubmit.call(this); + } - DisplaySettings.prototype.destroy = function () { - this.options = null; - }; + destroy() { + this.options = null; + } + } - return DisplaySettings; -}); +/* eslint-enable indent */ +export default DisplaySettings; diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 38715043e7..358bf04112 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -154,8 +154,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad html += '
'; } - var supportsImageAnalysis = appHost.supports('imageanalysis'); - var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle; + var cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle; cardLayout = false; html += cardBuilder.getCardsHtml(result.Items, { preferThumb: section.preferThumb, diff --git a/src/components/fetchhelper.js b/src/components/fetchhelper.js index f626abefee..00bffc235a 100644 --- a/src/components/fetchhelper.js +++ b/src/components/fetchhelper.js @@ -1,6 +1,5 @@ /* eslint-disable indent */ export function getFetchPromise(request) { - const headers = request.headers || {}; if (request.dataType === 'json') { @@ -16,7 +15,6 @@ let contentType = request.contentType; if (request.data) { - if (typeof request.data === 'string') { fetchRequest.body = request.data; } else { @@ -27,7 +25,6 @@ } if (contentType) { - headers['Content-Type'] = contentType; } @@ -48,11 +45,9 @@ } function fetchWithTimeout(url, options, timeoutMs) { - console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`); return new Promise(function (resolve, reject) { - const timeout = setTimeout(reject, timeoutMs); options = options || {}; @@ -65,7 +60,6 @@ resolve(response); }, function (error) { - clearTimeout(timeout); console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`); diff --git a/src/components/filterdialog/filterdialog.js b/src/components/filterdialog/filterdialog.js index 041fa82e76..df17c19dec 100644 --- a/src/components/filterdialog/filterdialog.js +++ b/src/components/filterdialog/filterdialog.js @@ -412,7 +412,7 @@ import 'css!./style.css'; dlg.classList.add('background-theme-a'); dlg.classList.add('formDialog'); dlg.classList.add('filterDialog'); - dlg.innerHTML = globalize.translateDocument(template); + dlg.innerHTML = globalize.translateHtml(template); setVisibility(dlg, this.options); dialogHelper.open(dlg); dlg.addEventListener('close', resolve); diff --git a/src/components/filtermenu/filtermenu.js b/src/components/filtermenu/filtermenu.js index c189856e7b..20399fb52d 100644 --- a/src/components/filtermenu/filtermenu.js +++ b/src/components/filtermenu/filtermenu.js @@ -2,19 +2,15 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'use strict'; function onSubmit(e) { - e.preventDefault(); return false; } function renderOptions(context, selector, cssClass, items, isCheckedFn) { - var elem = context.querySelector(selector); if (items.length) { - elem.classList.remove('hide'); - } else { elem.classList.add('hide'); } @@ -22,7 +18,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', var html = ''; html += items.map(function (filter) { - var itemHtml = ''; var checkedHtml = isCheckedFn(filter) ? ' checked' : ''; @@ -32,45 +27,20 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', itemHtml += ''; return itemHtml; - }).join(''); elem.querySelector('.filterOptions').innerHTML = html; } function renderDynamicFilters(context, result, options) { - - // If there's a huge number of these they will be really show to render - //if (result.Tags) { - // result.Tags.length = Math.min(result.Tags.length, 50); - //} - renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) { - // Switching from | to , var delimeter = (options.settings.GenreIds || '').indexOf('|') === -1 ? ',' : '|'; return (delimeter + (options.settings.GenreIds || '') + delimeter).indexOf(delimeter + i.Id + delimeter) !== -1; }); - - //renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) { - // var delimeter = '|'; - // return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1; - //}); - - //renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) { - // var delimeter = '|'; - // return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1; - //}); - - //renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) { - - // var delimeter = ','; - // return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1; - //}); } function loadDynamicFilters(context, options) { - var apiClient = connectionManager.getApiClient(options.serverId); var filterMenuOptions = Object.assign(options.filterMenuOptions, { @@ -81,16 +51,11 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', }); apiClient.getFilters(filterMenuOptions).then(function (result) { - renderDynamicFilters(context, result, options); - }, function () { - - // older server }); } function initEditor(context, settings) { - context.querySelector('form').addEventListener('submit', onSubmit); var elems = context.querySelectorAll('.simpleFilter'); @@ -98,7 +63,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', var length; for (i = 0, length = elems.length; i < length; i++) { - if (elems[i].tagName === 'INPUT') { elems[i].checked = settings[elems[i].getAttribute('data-settingname')] || false; } else { @@ -110,7 +74,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', elems = context.querySelectorAll('.chkVideoTypeFilter'); for (i = 0, length = elems.length; i < length; i++) { - elems[i].checked = videoTypes.indexOf(elems[i].getAttribute('data-filter')) !== -1; } @@ -118,7 +81,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', elems = context.querySelectorAll('.chkSeriesStatus'); for (i = 0, length = elems.length; i < length; i++) { - elems[i].checked = seriesStatuses.indexOf(elems[i].getAttribute('data-filter')) !== -1; } @@ -136,12 +98,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } function saveValues(context, settings, settingsKey) { - var elems = context.querySelectorAll('.simpleFilter'); var i; var length; for (i = 0, length = elems.length; i < length; i++) { - if (elems[i].tagName === 'INPUT') { setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i]); } else { @@ -154,7 +114,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', elems = context.querySelectorAll('.chkVideoTypeFilter'); for (i = 0, length = elems.length; i < length; i++) { - if (elems[i].checked) { videoTypes.push(elems[i].getAttribute('data-filter')); } @@ -166,7 +125,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', elems = context.querySelectorAll('.chkSeriesStatus'); for (i = 0, length = elems.length; i < length; i++) { - if (elems[i].checked) { seriesStatuses.push(elems[i].getAttribute('data-filter')); } @@ -177,7 +135,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', elems = context.querySelectorAll('.chkGenreFilter'); for (i = 0, length = elems.length; i < length; i++) { - if (elems[i].checked) { genres.push(elems[i].getAttribute('data-filter')); } @@ -186,7 +143,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } function setBasicFilter(context, key, elem) { - var value = elem.checked; value = value ? value : null; userSettings.setFilter(key, value); @@ -200,7 +156,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } function moveCheckboxFocus(elem, offset) { - var parent = dom.parentWithClass(elem, 'checkboxList-verticalwrap'); var elems = focusManager.getFocusableElements(parent); @@ -225,7 +180,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', function onInputCommand(e) { switch (e.detail.command) { - case 'left': moveCheckboxFocus(e.target, -1); e.preventDefault(); @@ -244,7 +198,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } function bindCheckboxInput(context, on) { - var elems = context.querySelectorAll('.checkboxList-verticalwrap'); for (var i = 0, length = elems.length; i < length; i++) { if (on) { @@ -256,11 +209,8 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } FilterMenu.prototype.show = function (options) { - return new Promise(function (resolve, reject) { - require(['text!./filtermenu.template.html'], function (template) { - var dialogOptions = { removeOnClose: true, scrollY: false @@ -286,7 +236,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', html += template; - dlg.innerHTML = globalize.translateDocument(html, 'core'); + dlg.innerHTML = globalize.translateHtml(html, 'core'); var settingElements = dlg.querySelectorAll('.viewSetting'); for (var i = 0, length = settingElements.length; i < length; i++) { @@ -303,7 +253,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', bindCheckboxInput(dlg, true); dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); }); @@ -314,17 +263,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', var submitted; dlg.querySelector('form').addEventListener('change', function () { - submitted = true; - //if (options.onChange) { - // saveValues(dlg, options.settings, options.settingsKey); - // options.onChange(); - //} - }, true); dialogHelper.open(dlg).then(function () { - bindCheckboxInput(dlg, false); if (layoutManager.tv) { @@ -332,7 +274,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', } if (submitted) { - //if (!options.onChange) { saveValues(dlg, options.settings, options.settingsKey); resolve(); diff --git a/src/components/focusManager.js b/src/components/focusManager.js index f2022cc445..9c495bf952 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -7,14 +7,12 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function popScope(elem) { - if (scopes.length) { scopes.length -= 1; } } function autoFocus(view, defaultToFirst, findAutoFocusElement) { - var element; if (findAutoFocusElement !== false) { element = view.querySelector('*[autofocus]'); @@ -37,7 +35,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function focus(element) { - try { element.focus({ preventScroll: scrollManager.isEnabled() @@ -50,16 +47,13 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A']; var focusableContainerTagNames = ['BODY', 'DIALOG']; var focusableQuery = focusableTagNames.map(function (t) { - if (t === 'INPUT') { t += ':not([type="range"]):not([type="file"])'; } return t + ':not([tabindex="-1"]):not(:disabled)'; - }).join(',') + ',.focusable'; function isFocusable(elem) { - if (focusableTagNames.indexOf(elem.tagName) !== -1) { return true; } @@ -83,7 +77,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function focusableParent(elem) { - var originalElement = elem; while (!isFocusable(elem)) { @@ -101,7 +94,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { // Determines if a focusable element can be focused at a given point in time function isCurrentlyFocusableInternal(elem) { - // http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom if (elem.offsetParent === null) { return false; @@ -112,7 +104,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { // Determines if a focusable element can be focused at a given point in time function isCurrentlyFocusable(elem) { - if (elem.disabled) { return false; } @@ -143,7 +134,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var focusableElements = []; for (var i = 0, length = elems.length; i < length; i++) { - var elem = elems[i]; if (excludeClass && elem.classList.contains(excludeClass)) { @@ -163,7 +153,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function isFocusContainer(elem, direction) { - if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) { return true; } @@ -217,7 +206,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function getOffset(elem) { - var box; // Support: BlackBerry 5, iOS 3 (original iPhone) @@ -234,7 +222,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } if (box.right === null) { - // Create a new object because some browsers will throw an error when trying to set data onto the Rect object var newBox = { top: box.top, @@ -253,7 +240,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function nav(activeElement, direction, container, focusableElements) { - activeElement = activeElement || document.activeElement; if (activeElement) { @@ -272,14 +258,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var rect = getOffset(activeElement); // Get elements and work out x/y points - var cache = []; var point1x = parseFloat(rect.left) || 0; var point1y = parseFloat(rect.top) || 0; var point2x = parseFloat(point1x + rect.width - 1) || point1x; var point2y = parseFloat(point1y + rect.height - 1) || point1y; - // Shortcuts to help with compression - var min = Math.min; - var max = Math.max; var sourceMidX = rect.left + (rect.width / 2); var sourceMidY = rect.top + (rect.height / 2); @@ -301,10 +283,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { continue; } - //if (!isCurrentlyFocusableInternal(curr)) { - // continue; - //} - var elementRect = getOffset(curr); // not currently visible @@ -313,7 +291,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } switch (direction) { - case 0: // left if (elementRect.left >= rect.left) { @@ -369,7 +346,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var distY; switch (direction) { - case 0: // left distX = Math.abs(point1x - Math.min(point1x, x2)); @@ -403,7 +379,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } if (nearestElement) { - // See if there's a focusable container, and if so, send the focus command to that if (activeElement) { var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable'); @@ -418,12 +393,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function intersectsInternal(a1, a2, b1, b2) { - return (b1 >= a1 && b1 <= a2) || (b2 >= a1 && b2 <= a2); } function intersects(a1, a2, b1, b2) { - return intersectsInternal(a1, a2, b1, b2) || intersectsInternal(b1, b2, a1, a2); } @@ -434,11 +407,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function focusFirst(container, focusableSelector) { - var elems = container.querySelectorAll(focusableSelector); for (var i = 0, length = elems.length; i < length; i++) { - var elem = elems[i]; if (isCurrentlyFocusableInternal(elem)) { @@ -449,11 +420,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function focusLast(container, focusableSelector) { - var elems = [].slice.call(container.querySelectorAll(focusableSelector), 0).reverse(); for (var i = 0, length = elems.length; i < length; i++) { - var elem = elems[i]; if (isCurrentlyFocusableInternal(elem)) { @@ -464,7 +433,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { } function moveFocus(sourceElement, container, focusableSelector, offset) { - var elems = container.querySelectorAll(focusableSelector); var list = []; var i; @@ -472,7 +440,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var elem; for (i = 0, length = elems.length; i < length; i++) { - elem = elems[i]; if (isCurrentlyFocusableInternal(elem)) { @@ -483,7 +450,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) { var currentIndex = -1; for (i = 0, length = list.length; i < length; i++) { - elem = list[i]; if (sourceElement === elem || elem.contains(sourceElement)) { diff --git a/src/components/groupedcards.js b/src/components/groupedcards.js index 5f23d8bb18..8ac3cc799c 100644 --- a/src/components/groupedcards.js +++ b/src/components/groupedcards.js @@ -1,5 +1,8 @@ -define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) { - 'use strict'; +/* eslint-disable indent */ + +import dom from 'dom'; +import appRouter from 'appRouter'; +import connectionManager from 'connectionManager'; function onGroupedCardClick(e, card) { var itemId = card.getAttribute('data-id'); @@ -31,7 +34,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn } } - function onItemsContainerClick(e) { + export default function onItemsContainerClick(e) { var groupedCard = dom.parentWithClass(e.target, 'groupedCard'); if (groupedCard) { @@ -39,7 +42,4 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn } } - return { - onItemsContainerClick: onItemsContainerClick - }; -}); +/* eslint-enable indent */ diff --git a/src/components/guide/guide-settings.js b/src/components/guide/guide-settings.js index 7409a7e943..c3ba49f283 100644 --- a/src/components/guide/guide-settings.js +++ b/src/components/guide/guide-settings.js @@ -2,12 +2,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio 'use strict'; function saveCategories(context, options) { - var categories = []; var chkCategorys = context.querySelectorAll('.chkCategory'); for (var i = 0, length = chkCategorys.length; i < length; i++) { - var type = chkCategorys[i].getAttribute('data-type'); if (chkCategorys[i].checked) { @@ -25,12 +23,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio } function loadCategories(context, options) { - var selectedCategories = options.categories || []; var chkCategorys = context.querySelectorAll('.chkCategory'); for (var i = 0, length = chkCategorys.length; i < length; i++) { - var type = chkCategorys[i].getAttribute('data-type'); chkCategorys[i].checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1; @@ -38,13 +34,11 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio } function save(context) { - var i; var length; var chkIndicators = context.querySelectorAll('.chkIndicator'); for (i = 0, length = chkIndicators.length; i < length; i++) { - var type = chkIndicators[i].getAttribute('data-type'); userSettings.set('guide-indicator-' + type, chkIndicators[i].checked); } @@ -62,13 +56,11 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio } function load(context) { - var i; var length; var chkIndicators = context.querySelectorAll('.chkIndicator'); for (i = 0, length = chkIndicators.length; i < length; i++) { - var type = chkIndicators[i].getAttribute('data-type'); if (chkIndicators[i].getAttribute('data-default') === 'true') { @@ -90,13 +82,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio } function showEditor(options) { - return new Promise(function (resolve, reject) { - var settingsChanged = false; require(['text!./guide-settings.template.html'], function (template) { - var dialogOptions = { removeOnClose: true, scrollY: false @@ -114,17 +103,15 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio var html = ''; - html += globalize.translateDocument(template, 'core'); + html += globalize.translateHtml(template, 'core'); dlg.innerHTML = html; dlg.addEventListener('change', function () { - settingsChanged = true; }); dlg.addEventListener('close', function () { - if (layoutManager.tv) { scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); } diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index 2c4a5c7604..bd3ad89aaa 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -2,7 +2,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'use strict'; function showViewSettings(instance) { - require(['guide-settings-dialog'], function (guideSettingsDialog) { guideSettingsDialog.show(instance.categoryOptions).then(function () { instance.refresh(); @@ -11,7 +10,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function updateProgramCellOnScroll(cell, scrollPct) { - var left = cell.posLeft; if (!left) { left = parseFloat(cell.style.left.replace('%', '')); @@ -43,11 +41,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', if (guideProgramName) { if (pctOfWidth > 0 && pctOfWidth <= 100) { - //guideProgramName.style.marginLeft = pctOfWidth + '%'; guideProgramName.style.transform = 'translateX(' + pctOfWidth + '%)'; caret.classList.remove('hide'); } else { - //guideProgramName.style.marginLeft = '0'; guideProgramName.style.transform = 'none'; caret.classList.add('hide'); } @@ -56,7 +52,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var isUpdatingProgramCellScroll = false; function updateProgramCellsOnScroll(programGrid, programCells) { - if (isUpdatingProgramCellScroll) { return; } @@ -64,13 +59,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', isUpdatingProgramCellScroll = true; requestAnimationFrame(function () { - var scrollLeft = programGrid.scrollLeft; var scrollPct = scrollLeft ? (scrollLeft / programGrid.scrollWidth) * 100 : 0; for (var i = 0, length = programCells.length; i < length; i++) { - updateProgramCellOnScroll(programCells[i], scrollPct); } @@ -79,14 +72,12 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function onProgramGridClick(e) { - if (!layoutManager.tv) { return; } var programCell = dom.parentWithClass(e.target, 'programCell'); if (programCell) { - var startDate = programCell.getAttribute('data-startdate'); var endDate = programCell.getAttribute('data-enddate'); startDate = datetime.parseISO8601Date(startDate, { toLocal: true }).getTime(); @@ -94,7 +85,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var now = new Date().getTime(); if (now >= startDate && now < endDate) { - var channelId = programCell.getAttribute('data-channelid'); var serverId = programCell.getAttribute('data-serverid'); @@ -110,7 +100,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function Guide(options) { - var self = this; var items = {}; @@ -121,7 +110,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var cellCurationMinutes = 30; var cellDurationMs = cellCurationMinutes * 60 * 1000; var msPerDay = 86400000; - var totalRendererdMs = msPerDay; var currentDate; var currentStartIndex = 0; @@ -132,7 +120,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var programGrid; self.refresh = function () { - currentDate = null; reloadPage(options.element); restartAutoRefresh(); @@ -151,7 +138,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', }; self.destroy = function () { - stopAutoRefresh(); events.off(serverNotifications, 'TimerCreated', onTimerCreated); @@ -165,7 +151,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', }; function restartAutoRefresh() { - stopAutoRefresh(); var intervalMs = 60000 * 15; // (minutes) @@ -183,15 +168,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function normalizeDateToTimeslot(date) { - var minutesOffset = date.getMinutes() - cellCurationMinutes; if (minutesOffset >= 0) { - date.setHours(date.getHours(), cellCurationMinutes, 0, 0); - } else { - date.setHours(date.getHours(), 0, 0, 0); } @@ -207,7 +188,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) { - var apiClient = connectionManager.getApiClient(options.serverId); var channelQuery = { @@ -290,12 +270,10 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', }; apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) { - var btnPreviousPage = context.querySelector('.btnPreviousPage'); var btnNextPage = context.querySelector('.btnNextPage'); if (channelsResult.TotalRecordCount > channelLimit) { - context.querySelector('.guideOptions').classList.remove('hide'); btnPreviousPage.classList.remove('hide'); @@ -312,7 +290,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } else { btnNextPage.disabled = true; } - } else { context.querySelector('.guideOptions').classList.add('hide'); } @@ -343,22 +320,17 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } apiClient.getLiveTvPrograms(programQuery).then(function (programsResult) { - renderGuide(context, date, channelsResult.Items, programsResult.Items, renderOptions, apiClient, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender); hideLoading(); - }); }); } function getDisplayTime(date) { - if ((typeof date).toString().toLowerCase() === 'string') { try { - date = datetime.parseISO8601Date(date, { toLocal: true }); - } catch (err) { return date; } @@ -368,7 +340,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function getTimeslotHeadersHtml(startDate, endDateTime) { - var html = ''; // clone @@ -377,7 +348,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', html += '
'; while (startDate.getTime() < endDateTime) { - html += '
'; html += getDisplayTime(startDate); @@ -411,23 +381,19 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function getTimerIndicator(item) { - var status; if (item.Type === 'SeriesTimer') { return ''; } else if (item.TimerId || item.SeriesTimerId) { - status = item.Status || 'Cancelled'; } else if (item.Type === 'Timer') { - status = item.Status; } else { return ''; } if (item.SeriesTimerId) { - if (status !== 'Cancelled') { return ''; } @@ -439,7 +405,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) { - var html = ''; var startMs = date.getTime(); @@ -463,11 +428,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var now = new Date().getTime(); for (var i = listInfo.startIndex, length = programs.length; i < length; i++) { - var program = programs[i]; if (program.ChannelId !== channel.Id) { - if (programsFound) { break; } @@ -577,7 +540,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', html += '
'; if (program.IsHD && options.showHdIcon) { - //html += ''; if (layoutManager.tv) { html += '
HD
'; } else { @@ -599,11 +561,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', } function renderChannelHeaders(context, channels, apiClient) { - var html = ''; for (var i = 0, length = channels.length; i < length; i++) { - var channel = channels[i]; var hasChannelImage = channel.ImageTags.Primary; @@ -615,18 +575,15 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', var title = []; if (channel.ChannelNumber) { - title.push(channel.ChannelNumber); } if (channel.Name) { - title.push(channel.Name); } html += ''; - currentHtml += ''; + currentHtml += ``; + currentHtml += ``; currentHtml += '
'; - index++; return currentHtml; - }).join(''); context.querySelector('.viewOrderList').innerHTML = html; } function updateHomeSectionValues(context, userSettings) { + for (let i = 1; i <= 7; i++) { + const select = context.querySelector(`#selectHomeSection${i}`); + const defaultValue = homeSections.getDefaultSection(i - 1); - for (var i = 1; i <= 7; i++) { + const option = select.querySelector(`option[value=${defaultValue}]`) || select.querySelector('option[value=""]'); - var select = context.querySelector('#selectHomeSection' + i); - var defaultValue = homeSections.getDefaultSection(i - 1); - - var option = select.querySelector('option[value=' + defaultValue + ']') || select.querySelector('option[value=""]'); - - var userValue = userSettings.get('homesection' + (i - 1)); + const userValue = userSettings.get(`homesection${i - 1}`); option.value = ''; @@ -192,43 +189,39 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) { + let html = ''; - var html = ''; - - var isChecked; + let isChecked; if (item.Type === 'Channel' || item.CollectionType === 'boxsets' || item.CollectionType === 'playlists') { - isChecked = (user.Configuration.MyMediaExcludes || []).indexOf(item.Id) === -1; + isChecked = !(user.Configuration.MyMediaExcludes || []).includes(item.Id); html += '
'; html += ''; html += '
'; } - var excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels']; - if (excludeFromLatest.indexOf(item.CollectionType || '') === -1) { - - isChecked = user.Configuration.LatestItemsExcludes.indexOf(item.Id) === -1; + const excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels']; + if (!excludeFromLatest.includes(item.CollectionType || '')) { + isChecked = !user.Configuration.LatestItemsExcludes.includes(item.Id); html += ''; } if (html) { - - html = '
' + html + '
'; + html = `
${html}
`; } if (item.CollectionType === 'movies' || item.CollectionType === 'tvshows' || item.CollectionType === 'music' || item.CollectionType === 'livetv') { - - var idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id; + const idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id; html += '
'; - html += '`; - var userValue = userSettings.get('landing-' + idForLanding); + const userValue = userSettings.get(`landing-${idForLanding}`); html += getLandingScreenOptionsHtml(item.CollectionType, userValue); @@ -237,8 +230,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } if (html) { - - var prefix = ''; + let prefix = ''; prefix += '
'; prefix += '

'; @@ -253,12 +245,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) { + const elem = context.querySelector('.perLibrarySettings'); + let html = ''; - var elem = context.querySelector('.perLibrarySettings'); - var html = ''; - - for (var i = 0, length = userViews.length; i < length; i++) { - + for (let i = 0, length = userViews.length; i < length; i++) { html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient); } @@ -266,16 +256,14 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function loadForm(context, user, userSettings, apiClient) { - context.querySelector('.chkHidePlayedFromLatest').checked = user.Configuration.HidePlayedInLatest || false; updateHomeSectionValues(context, userSettings); - var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id); - var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions')); - - Promise.all([promise1, promise2]).then(function (responses) { + const promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id); + const promise2 = apiClient.getJSON(apiClient.getUrl(`Users/${user.Id}/GroupingOptions`)); + Promise.all([promise1, promise2]).then(responses => { renderViewOrder(context, user, responses[0]); renderPerLibrarySettings(context, user, responses[0].Items, userSettings, apiClient); @@ -286,48 +274,23 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa }); } - function getSibling(elem, type, className) { - - var sibling = elem[type]; - - while (sibling != null) { - if (sibling.classList.contains(className)) { - break; - } - } - - if (sibling != null) { - if (!sibling.classList.contains(className)) { - sibling = null; - } - } - - return sibling; - } - function onSectionOrderListClick(e) { - - var target = dom.parentWithClass(e.target, 'btnViewItemMove'); + const target = dom.parentWithClass(e.target, 'btnViewItemMove'); if (target) { - var viewItem = dom.parentWithClass(target, 'viewItem'); + const viewItem = dom.parentWithClass(target, 'viewItem'); if (viewItem) { - var ul = dom.parentWithClass(viewItem, 'paperList'); - if (target.classList.contains('btnViewItemDown')) { - - var next = viewItem.nextSibling; + const next = viewItem.nextSibling; if (next) { viewItem.parentNode.removeChild(viewItem); next.parentNode.insertBefore(viewItem, next.nextSibling); focusManager.focus(e.target); } - } else { - - var prev = viewItem.previousSibling; + const prev = viewItem.previousSibling; if (prev) { viewItem.parentNode.removeChild(viewItem); @@ -340,44 +303,37 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function getCheckboxItems(selector, context, isChecked) { + const inputs = context.querySelectorAll(selector); + const list = []; - var inputs = context.querySelectorAll(selector); - var list = []; - - for (var i = 0, length = inputs.length; i < length; i++) { - + for (let i = 0, length = inputs.length; i < length; i++) { if (inputs[i].checked === isChecked) { list.push(inputs[i]); } - } return list; } function saveUser(context, user, userSettingsInstance, apiClient) { - user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked; - user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) { - + user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(i => { return i.getAttribute('data-folderid'); }); - user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) { - + user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(i => { return i.getAttribute('data-folderid'); }); - user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) { - + user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(i => { return i.getAttribute('data-folderid'); }); - var viewItems = context.querySelectorAll('.viewItem'); - var orderedViews = []; - var i; - var length; + const viewItems = context.querySelectorAll('.viewItem'); + const orderedViews = []; + let i; + let length; for (i = 0, length = viewItems.length; i < length; i++) { orderedViews.push(viewItems[i].getAttribute('data-viewid')); } @@ -394,48 +350,42 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa userSettingsInstance.set('homesection5', context.querySelector('#selectHomeSection6').value); userSettingsInstance.set('homesection6', context.querySelector('#selectHomeSection7').value); - var selectLandings = context.querySelectorAll('.selectLanding'); + const selectLandings = context.querySelectorAll('.selectLanding'); for (i = 0, length = selectLandings.length; i < length; i++) { - var selectLanding = selectLandings[i]; - userSettingsInstance.set('landing-' + selectLanding.getAttribute('data-folderid'), selectLanding.value); + const selectLanding = selectLandings[i]; + userSettingsInstance.set(`landing-${selectLanding.getAttribute('data-folderid')}`, selectLanding.value); } return apiClient.updateUserConfiguration(user.Id, user.Configuration); } function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) { - loading.show(); - apiClient.getUser(userId).then(function (user) { - - saveUser(context, user, userSettings, apiClient).then(function () { - + apiClient.getUser(userId).then(user => { + saveUser(context, user, userSettings, apiClient).then(() => { loading.hide(); if (enableSaveConfirmation) { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('SettingsSaved')); }); } events.trigger(instance, 'saved'); - - }, function () { + }, () => { loading.hide(); }); }); } function onSubmit(e) { + const self = this; + const apiClient = connectionManager.getApiClient(self.options.serverId); + const userId = self.options.userId; + const userSettings = self.options.userSettings; - 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; + userSettings.setUserInfo(userId, apiClient).then(() => { + const enableSaveConfirmation = self.options.enableSaveConfirmation; save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation); }); @@ -447,14 +397,13 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function onChange(e) { - - var chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia'); + const chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia'); if (!chkIncludeInMyMedia) { return; } - var section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection'); - var fldIncludeInLatest = section.querySelector('.fldIncludeInLatest'); + const section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection'); + const fldIncludeInLatest = section.querySelector('.fldIncludeInLatest'); if (fldIncludeInLatest) { if (chkIncludeInMyMedia.checked) { fldIncludeInLatest.classList.remove('hide'); @@ -465,14 +414,12 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa } function embed(options, self) { - - require(['text!./homeScreenSettings.template.html'], function (template) { - - for (var i = 1; i <= numConfigurableSections; i++) { - template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i)); + return import('text!./homeScreenSettings.template.html').then(({default: template}) => { + for (let i = 1; i <= numConfigurableSections; i++) { + template = template.replace(`{section${i}label}`, globalize.translate('LabelHomeScreenSectionValue', i)); } - options.element.innerHTML = globalize.translateDocument(template, 'core'); + options.element.innerHTML = globalize.translateHtml(template, 'core'); options.element.querySelector('.viewOrderList').addEventListener('click', onSectionOrderListClick); options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); @@ -492,47 +439,44 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa }); } - function HomeScreenSettings(options) { + class HomeScreenSettings { + constructor(options) { + this.options = options; + embed(options, this); + } - this.options = options; + loadData(autoFocus) { + const self = this; + const context = self.options.element; - embed(options, this); + loading.show(); + + const userId = self.options.userId; + const apiClient = connectionManager.getApiClient(self.options.serverId); + const userSettings = self.options.userSettings; + + apiClient.getUser(userId).then(user => { + userSettings.setUserInfo(userId, apiClient).then(() => { + self.dataLoaded = true; + + loadForm(context, user, userSettings, apiClient); + + if (autoFocus) { + focusManager.autoFocus(context); + } + }); + }); + } + + submit() { + onSubmit.call(this); + } + + destroy() { + this.options = null; + } } - HomeScreenSettings.prototype.loadData = function (autoFocus) { +/* eslint-enable indent */ - var self = this; - var context = self.options.element; - - loading.show(); - - var userId = self.options.userId; - var apiClient = connectionManager.getApiClient(self.options.serverId); - var userSettings = self.options.userSettings; - - apiClient.getUser(userId).then(function (user) { - - userSettings.setUserInfo(userId, apiClient).then(function () { - - self.dataLoaded = true; - - loadForm(context, user, userSettings, apiClient); - - if (autoFocus) { - focusManager.autoFocus(context); - } - }); - }); - }; - - HomeScreenSettings.prototype.submit = function () { - onSubmit.call(this); - }; - - HomeScreenSettings.prototype.destroy = function () { - - this.options = null; - }; - - return HomeScreenSettings; -}); +export default HomeScreenSettings; diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index bba4b9db1b..6198894088 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -1,7 +1,20 @@ -define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) { - 'use strict'; +import connectionManager from 'connectionManager'; +import cardBuilder from 'cardBuilder'; +import dom from 'dom'; +import layoutManager from 'layoutManager'; +import imageLoader from 'imageLoader'; +import globalize from 'globalize'; +import appRouter from 'appRouter'; +import imageHelper from 'scripts/imagehelper'; +import 'paper-icon-button-light'; +import 'emby-itemscontainer'; +import 'emby-scroller'; +import 'emby-button'; +import 'css!./homesections'; - function getDefaultSection(index) { +/* eslint-disable indent */ + + export function getDefaultSection(index) { switch (index) { case 0: return 'smalllibrarytiles'; @@ -23,9 +36,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getAllSectionsToShow(userSettings, sectionCount) { - var sections = []; - for (var i = 0, length = sectionCount; i < length; i++) { - var section = userSettings.get('homesection' + i) || getDefaultSection(i); + const sections = []; + for (let i = 0, length = sectionCount; i < length; i++) { + let section = userSettings.get('homesection' + i) || getDefaultSection(i); if (section === 'folders') { section = getDefaultSection(0); } @@ -36,22 +49,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la return sections; } - function loadSections(elem, apiClient, user, userSettings) { + export function loadSections(elem, apiClient, user, userSettings) { return getUserViews(apiClient, user.Id).then(function (userViews) { - var html = ''; + let html = ''; if (userViews.length) { - var sectionCount = 7; - for (var i = 0; i < sectionCount; i++) { + const sectionCount = 7; + for (let i = 0; i < sectionCount; i++) { html += '
'; } elem.innerHTML = html; elem.classList.add('homeSectionsContainer'); - var promises = []; - var sections = getAllSectionsToShow(userSettings, sectionCount); - for (var i = 0; i < sections.length; i++) { + const promises = []; + const sections = getAllSectionsToShow(userSettings, sectionCount); + for (let i = 0; i < sections.length; i++) { promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i)); } @@ -62,7 +75,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la }); }); } else { - var noLibDescription; + let noLibDescription; if (user['Policy'] && user['Policy']['IsAdministrator']) { noLibDescription = globalize.translate('NoCreatedLibraries', '
', ''); } else { @@ -75,7 +88,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la html += '

'; elem.innerHTML = html; - var createNowLink = elem.querySelector('#button-createLibrary'); + const createNowLink = elem.querySelector('#button-createLibrary'); if (createNowLink) { createNowLink.addEventListener('click', function () { Dashboard.navigate('library.html'); @@ -85,9 +98,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la }); } - function destroySections(elem) { - var elems = elem.querySelectorAll('.itemsContainer'); - for (var i = 0; i < elems.length; i++) { + export function destroySections(elem) { + const elems = elem.querySelectorAll('.itemsContainer'); + for (let i = 0; i < elems.length; i++) { elems[i].fetchData = null; elems[i].parentContainer = null; elems[i].getItemsHtml = null; @@ -96,35 +109,32 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.innerHTML = ''; } - function pause(elem) { - var elems = elem.querySelectorAll('.itemsContainer'); - for (var i = 0; i < elems.length; i++) { + export function pause(elem) { + const elems = elem.querySelectorAll('.itemsContainer'); + for (let i = 0; i < elems.length; i++) { elems[i].pause(); } } - function resume(elem, options) { - var elems = elem.querySelectorAll('.itemsContainer'); - var i; - var length; - var promises = []; + export function resume(elem, options) { + const elems = elem.querySelectorAll('.itemsContainer'); + const promises = []; - for (i = 0, length = elems.length; i < length; i++) { + for (let i = 0, length = elems.length; i < length; i++) { promises.push(elems[i].resume(options)); } - var promise = Promise.all(promises); + const promise = Promise.all(promises); if (!options || options.returnPromise !== false) { return promise; } } function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) { + const section = allSections[index]; + const userId = user.Id; - var section = allSections[index]; - var userId = user.Id; - - var elem = page.querySelector('.section' + index); + const elem = page.querySelector('.section' + index); if (section === 'latestmedia') { loadRecentlyAdded(elem, apiClient, user, userViews); @@ -172,7 +182,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getLibraryButtonsHtml(items) { - var html = ''; + let html = ''; html += '
'; html += '

' + globalize.translate('HeaderMyMedia') + '

'; @@ -180,9 +190,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la html += '
'; // library card background images - for (var i = 0, length = items.length; i < length; i++) { - var item = items[i]; - var icon = imageHelper.getLibraryIcon(item.CollectionType); + for (let i = 0, length = items.length; i < length; i++) { + const item = items[i]; + const icon = imageHelper.getLibraryIcon(item.CollectionType); html += '' + item.Name + ''; } @@ -194,24 +204,16 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function loadlibraryButtons(elem, apiClient, user, userSettings, userViews) { elem.classList.remove('verticalSection'); - var html = getLibraryButtonsHtml(userViews); + const html = getLibraryButtonsHtml(userViews); elem.innerHTML = html; imageLoader.lazyChildren(elem); } - /** - * Returns a random integer between min (inclusive) and max (inclusive) - * Using Math.round() will give you a non-uniform distribution! - */ - function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - } - function getFetchLatestItemsFn(serverId, parentId, collectionType) { return function () { - var apiClient = connectionManager.getApiClient(serverId); - var limit = 16; + const apiClient = connectionManager.getApiClient(serverId); + let limit = 16; if (enableScrollX()) { if (collectionType === 'music') { @@ -227,7 +229,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } } - var options = { + const options = { Limit: limit, Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path', ImageTypeLimit: 1, @@ -241,8 +243,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getLatestItemsHtmlFn(itemType, viewType) { return function (items) { - var cardLayout = false; - var shape; + const cardLayout = false; + let shape; if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') { shape = getPortraitShape(); } else if (viewType === 'music' || viewType === 'homevideos') { @@ -272,7 +274,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function renderLatestSection(elem, apiClient, user, parent) { - var html = ''; + let html = ''; html += '
'; if (!layoutManager.tv) { @@ -303,7 +305,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType); itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType); itemsContainer.parentContainer = elem; @@ -311,10 +313,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function loadRecentlyAdded(elem, apiClient, user, userViews) { elem.classList.remove('verticalSection'); - var excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels']; + const excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels']; - for (var i = 0, length = userViews.length; i < length; i++) { - var item = userViews[i]; + for (let i = 0, length = userViews.length; i < length; i++) { + const item = userViews[i]; if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) { continue; } @@ -323,7 +325,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la continue; } - var frag = document.createElement('div'); + const frag = document.createElement('div'); frag.classList.add('verticalSection'); frag.classList.add('hide'); elem.appendChild(frag); @@ -332,14 +334,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } } - function getRequirePromise(deps) { - return new Promise(function (resolve, reject) { - require(deps, resolve); - }); - } - - function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) { - var html = ''; + export function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) { + let html = ''; if (userViews.length) { html += '

' + globalize.translate('HeaderMyMedia') + '

'; if (enableScrollX()) { @@ -372,10 +368,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getContinueWatchingFetchFn(serverId) { return function () { - var apiClient = connectionManager.getApiClient(serverId); - var screenWidth = dom.getWindowSize().innerWidth; + const apiClient = connectionManager.getApiClient(serverId); + const screenWidth = dom.getWindowSize().innerWidth; - var limit; + let limit; if (enableScrollX()) { limit = 12; } else { @@ -383,7 +379,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la limit = Math.min(limit, 5); } - var options = { + const options = { Limit: limit, Recursive: true, Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', @@ -398,7 +394,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getContinueWatchingItemsHtml(items) { - var cardLayout = false; + const cardLayout = false; return cardBuilder.getCardsHtml({ items: items, preferThumb: true, @@ -419,7 +415,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function loadResumeVideo(elem, apiClient, userId) { - var html = ''; + let html = ''; html += '

' + globalize.translate('HeaderContinueWatching') + '

'; if (enableScrollX()) { @@ -437,7 +433,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.classList.add('hide'); elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.fetchData = getContinueWatchingFetchFn(apiClient.serverId()); itemsContainer.getItemsHtml = getContinueWatchingItemsHtml; itemsContainer.parentContainer = elem; @@ -445,10 +441,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getContinueListeningFetchFn(serverId) { return function () { - var apiClient = connectionManager.getApiClient(serverId); - var screenWidth = dom.getWindowSize().innerWidth; + const apiClient = connectionManager.getApiClient(serverId); + const screenWidth = dom.getWindowSize().innerWidth; - var limit; + let limit; if (enableScrollX()) { limit = 12; } else { @@ -456,7 +452,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la limit = Math.min(limit, 5); } - var options = { + const options = { Limit: limit, Recursive: true, Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', @@ -471,7 +467,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getContinueListeningItemsHtml(items) { - var cardLayout = false; + const cardLayout = false; return cardBuilder.getCardsHtml({ items: items, preferThumb: true, @@ -492,7 +488,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function loadResumeAudio(elem, apiClient, userId) { - var html = ''; + let html = ''; html += '

' + globalize.translate('HeaderContinueWatching') + '

'; if (enableScrollX()) { @@ -510,7 +506,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.classList.add('hide'); elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.fetchData = getContinueListeningFetchFn(apiClient.serverId()); itemsContainer.getItemsHtml = getContinueListeningItemsHtml; itemsContainer.parentContainer = elem; @@ -518,7 +514,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getOnNowFetchFn(serverId) { return function () { - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); return apiClient.getLiveTvRecommendedPrograms({ userId: apiClient.getCurrentUserId(), IsAiring: true, @@ -532,7 +528,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getOnNowItemsHtml(items) { - var cardLayout = false; return cardBuilder.getCardsHtml({ items: items, preferThumb: 'auto', @@ -559,7 +554,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la return Promise.resolve(); } - var userId = user.Id; return apiClient.getLiveTvRecommendedPrograms({ userId: apiClient.getCurrentUserId(), IsAiring: true, @@ -569,7 +563,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la EnableTotalRecordCount: false, Fields: 'ChannelInfo,PrimaryImageAspectRatio' }).then(function (result) { - var html = ''; + let html = ''; if (result.Items.length) { elem.classList.remove('padded-left'); elem.classList.remove('padded-right'); @@ -632,7 +626,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la html += '

'; html += ''; html += ''; - } else { html += '

' + globalize.translate('HeaderOnNow') + '

'; } @@ -654,7 +647,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.parentContainer = elem; itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId()); itemsContainer.getItemsHtml = getOnNowItemsHtml; @@ -664,7 +657,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getNextUpFetchFn(serverId) { return function () { - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); return apiClient.getNextUpEpisodes({ Limit: enableScrollX() ? 24 : 15, Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path', @@ -677,7 +670,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function getNextUpItemsHtml(items) { - var cardLayout = false; + const cardLayout = false; return cardBuilder.getCardsHtml({ items: items, preferThumb: true, @@ -695,7 +688,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function loadNextUp(elem, apiClient, userId) { - var html = ''; + let html = ''; html += '
'; if (!layoutManager.tv) { @@ -727,7 +720,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.classList.add('hide'); elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId()); itemsContainer.getItemsHtml = getNextUpItemsHtml; itemsContainer.parentContainer = elem; @@ -735,7 +728,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) { return function () { - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); return apiClient.getLiveTvRecordings({ userId: apiClient.getCurrentUserId(), Limit: enableScrollX() ? 12 : 5, @@ -749,7 +742,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la function getLatestRecordingItemsHtml(activeRecordingsOnly) { return function (items) { - var cardLayout = false; return cardBuilder.getCardsHtml({ items: items, shape: enableScrollX() ? 'autooverflow' : 'auto', @@ -774,11 +766,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la } function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) { - var title = activeRecordingsOnly ? + const title = activeRecordingsOnly ? globalize.translate('HeaderActiveRecordings') : globalize.translate('HeaderLatestRecordings'); - var html = ''; + let html = ''; html += '
'; html += '

' + title + '

'; @@ -799,18 +791,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la elem.classList.add('hide'); elem.innerHTML = html; - var itemsContainer = elem.querySelector('.itemsContainer'); + const itemsContainer = elem.querySelector('.itemsContainer'); itemsContainer.fetchData = getLatestRecordingsFetchFn(apiClient.serverId(), activeRecordingsOnly); itemsContainer.getItemsHtml = getLatestRecordingItemsHtml(activeRecordingsOnly); itemsContainer.parentContainer = elem; } - return { - loadLibraryTiles: loadLibraryTiles, - getDefaultSection: getDefaultSection, - loadSections: loadSections, - destroySections: destroySections, - pause: pause, - resume: resume - }; -}); +export default { + loadLibraryTiles: loadLibraryTiles, + getDefaultSection: getDefaultSection, + loadSections: loadSections, + destroySections: destroySections, + pause: pause, + resume: resume +}; + +/* eslint-enable indent */ diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index 3f17eeb336..4095502aae 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -1,17 +1,20 @@ -define(['appSettings', 'browser', 'events'], function (appSettings, browser, events) { - 'use strict'; +/* eslint-disable indent */ - function getSavedVolume() { +import appSettings from 'appSettings' ; +import browser from 'browser'; +import events from 'events'; + + export function getSavedVolume() { return appSettings.get('volume') || 1; } - function saveVolume(value) { + export function saveVolume(value) { if (value) { appSettings.set('volume', value); } } - function getCrossOriginValue(mediaSource) { + export function getCrossOriginValue(mediaSource) { if (mediaSource.IsRemote) { return null; } @@ -30,34 +33,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve return false; } - function enableHlsShakaPlayer(item, mediaSource, mediaType) { - /* eslint-disable-next-line compat/compat */ - if (!!window.MediaSource && !!MediaSource.isTypeSupported) { - - if (canPlayNativeHls()) { - - if (browser.edge && mediaType === 'Video') { - return true; - } - - // simple playback should use the native support - if (mediaSource.RunTimeTicks) { - //if (!browser.edge) { - //return false; - //} - } - - //return false; - } - - return true; - } - - return false; - } - - function enableHlsJsPlayer(runTimeTicks, mediaType) { - + export function enableHlsJsPlayer(runTimeTicks, mediaType) { if (window.MediaSource == null) { return false; } @@ -73,7 +49,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } if (canPlayNativeHls()) { - // Having trouble with chrome's native support and transcoded music if (browser.android && mediaType === 'Audio') { return true; @@ -98,8 +73,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve var recoverDecodingErrorDate; var recoverSwapAudioCodecDate; - function handleHlsJsMediaError(instance, reject) { - + export function handleHlsJsMediaError(instance, reject) { var hlsPlayer = instance._hlsPlayer; if (!hlsPlayer) { @@ -134,8 +108,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function onErrorInternal(instance, type) { - + export function onErrorInternal(instance, type) { // Needed for video if (instance.destroyCustomTrack) { instance.destroyCustomTrack(instance._mediaElement); @@ -148,7 +121,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve ]); } - function isValidDuration(duration) { + export function isValidDuration(duration) { if (duration && !isNaN(duration) && duration !== Number.POSITIVE_INFINITY && duration !== Number.NEGATIVE_INFINITY) { return true; } @@ -162,13 +135,10 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function seekOnPlaybackStart(instance, element, ticks, onMediaReady) { - + export function seekOnPlaybackStart(instance, element, ticks, onMediaReady) { var seconds = (ticks || 0) / 10000000; if (seconds) { - var src = (instance.currentSrc() || '').toLowerCase(); - // Appending #t=xxx to the query string doesn't seem to work with HLS // For plain video files, not all browsers support it either @@ -200,12 +170,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function applySrc(elem, src, options) { - + export function applySrc(elem, src, options) { if (window.Windows && options.mediaSource && options.mediaSource.IsLocal) { - return Windows.Storage.StorageFile.getFileFromPathAsync(options.url).then(function (file) { - var playlist = new Windows.Media.Playback.MediaPlaybackList(); var source1 = Windows.Media.Core.MediaSource.createFromStorageFile(file); @@ -214,9 +181,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve elem.src = URL.createObjectURL(playlist, { oneTimeOnly: true }); return Promise.resolve(); }); - } else { - elem.src = src; } @@ -224,18 +189,15 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } function onSuccessfulPlay(elem, onErrorFn) { - elem.addEventListener('error', onErrorFn); } - function playWithPromise(elem, onErrorFn) { - + export function playWithPromise(elem, onErrorFn) { try { var promise = elem.play(); if (promise && promise.then) { // Chrome now returns a promise return promise.catch(function (e) { - var errorName = (e.name || '').toLowerCase(); // safari uses aborterror if (errorName === 'notallowederror' || @@ -256,8 +218,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function destroyCastPlayer(instance) { - + export function destroyCastPlayer(instance) { var player = instance._castPlayer; if (player) { try { @@ -270,20 +231,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function destroyShakaPlayer(instance) { - var player = instance._shakaPlayer; - if (player) { - try { - player.destroy(); - } catch (err) { - console.error(err); - } - - instance._shakaPlayer = null; - } - } - - function destroyHlsPlayer(instance) { + export function destroyHlsPlayer(instance) { var player = instance._hlsPlayer; if (player) { try { @@ -296,7 +244,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function destroyFlvPlayer(instance) { + export function destroyFlvPlayer(instance) { var player = instance._flvPlayer; if (player) { try { @@ -311,11 +259,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } } - function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) { - + export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) { hls.on(Hls.Events.MANIFEST_PARSED, function () { playWithPromise(elem, onErrorFn).then(resolve, function () { - if (reject) { reject(); reject = null; @@ -324,14 +270,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve }); hls.on(Hls.Events.ERROR, function (event, data) { - console.error('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false)); switch (data.type) { case Hls.ErrorTypes.NETWORK_ERROR: // try to recover network error if (data.response && data.response.code && data.response.code >= 400) { - console.debug('hls.js response error code: ' + data.response.code); // Trigger failure differently depending on whether this is prior to start of playback, or after @@ -345,7 +289,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve } return; - } break; @@ -358,7 +301,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve case Hls.ErrorTypes.NETWORK_ERROR: if (data.response && data.response.code === 0) { - // This could be a CORS error related to access control response headers console.debug('hls.js response error code: ' + data.response.code); @@ -403,8 +345,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve }); } - function onEndedInternal(instance, elem, onErrorFn) { - + export function onEndedInternal(instance, elem, onErrorFn) { elem.removeEventListener('error', onErrorFn); elem.src = ''; @@ -413,7 +354,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve destroyHlsPlayer(instance); destroyFlvPlayer(instance); - destroyShakaPlayer(instance); destroyCastPlayer(instance); var stopInfo = { @@ -427,8 +367,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve instance._currentPlayOptions = null; } - function getBufferedRanges(instance, elem) { - + export function getBufferedRanges(instance, elem) { var ranges = []; var seekable = elem.buffered || []; @@ -441,7 +380,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve offset = offset || 0; for (var i = 0, length = seekable.length; i < length; i++) { - var start = seekable.start(i); var end = seekable.end(i); @@ -462,23 +400,4 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve return ranges; } - return { - getSavedVolume: getSavedVolume, - saveVolume: saveVolume, - enableHlsJsPlayer: enableHlsJsPlayer, - enableHlsShakaPlayer: enableHlsShakaPlayer, - handleHlsJsMediaError: handleHlsJsMediaError, - isValidDuration: isValidDuration, - onErrorInternal: onErrorInternal, - seekOnPlaybackStart: seekOnPlaybackStart, - applySrc: applySrc, - playWithPromise: playWithPromise, - destroyHlsPlayer: destroyHlsPlayer, - destroyFlvPlayer: destroyFlvPlayer, - destroyCastPlayer: destroyCastPlayer, - bindEventsToHlsPlayer: bindEventsToHlsPlayer, - onEndedInternal: onEndedInternal, - getCrossOriginValue: getCrossOriginValue, - getBufferedRanges: getBufferedRanges - }; -}); +/* eslint-enable indent */ diff --git a/src/components/imageDownloader/imageDownloader.js b/src/components/imageDownloader/imageDownloader.js index a3965279cf..2be2ef09b2 100644 --- a/src/components/imageDownloader/imageDownloader.js +++ b/src/components/imageDownloader/imageDownloader.js @@ -1,24 +1,39 @@ -define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (dom, loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { - 'use strict'; +import dom from 'dom'; +import loading from 'loading'; +import appHost from 'apphost'; +import dialogHelper from 'dialogHelper'; +import connectionManager from 'connectionManager'; +import imageLoader from 'imageLoader'; +import browser from 'browser'; +import layoutManager from 'layoutManager'; +import scrollHelper from 'scrollHelper'; +import globalize from 'globalize'; +import require from 'require'; +import 'emby-checkbox'; +import 'paper-icon-button-light'; +import 'emby-button'; +import 'formDialogStyle'; +import 'cardStyle'; - var enableFocusTransform = !browser.slow && !browser.edge; +/* eslint-disable indent */ - var currentItemId; - var currentItemType; - var currentResolve; - var currentReject; - var hasChanges = false; + const enableFocusTransform = !browser.slow && !browser.edge; + + let currentItemId; + let currentItemType; + let currentResolve; + let currentReject; + let hasChanges = false; // These images can be large and we're seeing memory problems in safari - var browsableImagePageSize = browser.slow ? 6 : 30; + const browsableImagePageSize = browser.slow ? 6 : 30; - var browsableImageStartIndex = 0; - var browsableImageType = 'Primary'; - var selectedProvider; + let browsableImageStartIndex = 0; + let browsableImageType = 'Primary'; + let selectedProvider; function getBaseRemoteOptions() { - - var options = {}; + const options = {}; options.itemId = currentItemId; @@ -26,58 +41,53 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } function reloadBrowsableImages(page, apiClient) { - loading.show(); - var options = getBaseRemoteOptions(); + const options = getBaseRemoteOptions(); options.type = browsableImageType; options.startIndex = browsableImageStartIndex; options.limit = browsableImagePageSize; options.IncludeAllLanguages = page.querySelector('#chkAllLanguages').checked; - var provider = selectedProvider || ''; + const provider = selectedProvider || ''; if (provider) { options.ProviderName = provider; } apiClient.getAvailableRemoteImages(options).then(function (result) { - renderRemoteImages(page, apiClient, result, browsableImageType, options.startIndex, options.limit); page.querySelector('#selectBrowsableImageType').value = browsableImageType; - var providersHtml = result.Providers.map(function (p) { + const providersHtml = result.Providers.map(function (p) { return ''; }); - var selectImageProvider = page.querySelector('#selectImageProvider'); + const selectImageProvider = page.querySelector('#selectImageProvider'); selectImageProvider.innerHTML = '' + providersHtml; selectImageProvider.value = provider; loading.hide(); }); - } function renderRemoteImages(page, apiClient, imagesResult, imageType, startIndex, limit) { - page.querySelector('.availableImagesPaging').innerHTML = getPagingHtml(startIndex, limit, imagesResult.TotalRecordCount); - var html = ''; - - for (var i = 0, length = imagesResult.Images.length; i < length; i++) { + let html = ''; + for (let i = 0, length = imagesResult.Images.length; i < length; i++) { html += getRemoteImageHtml(imagesResult.Images[i], imageType, apiClient); } - var availableImagesList = page.querySelector('.availableImagesList'); + const availableImagesList = page.querySelector('.availableImagesList'); availableImagesList.innerHTML = html; imageLoader.lazyChildren(availableImagesList); - var btnNextPage = page.querySelector('.btnNextPage'); - var btnPreviousPage = page.querySelector('.btnPreviousPage'); + const btnNextPage = page.querySelector('.btnNextPage'); + const btnPreviousPage = page.querySelector('.btnPreviousPage'); if (btnNextPage) { btnNextPage.addEventListener('click', function () { @@ -92,23 +102,21 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image reloadBrowsableImages(page, apiClient); }); } - } function getPagingHtml(startIndex, limit, totalRecordCount) { + let html = ''; - var html = ''; - - var recordsEnd = Math.min(startIndex + limit, totalRecordCount); + const recordsEnd = Math.min(startIndex + limit, totalRecordCount); // 20 is the minimum page size - var showControls = totalRecordCount > limit; + const showControls = totalRecordCount > limit; html += '
'; html += ''; - var startAtDisplay = totalRecordCount ? startIndex + 1 : 0; + const startAtDisplay = totalRecordCount ? startIndex + 1 : 0; html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount); html += ''; @@ -127,7 +135,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } function downloadRemoteImage(page, apiClient, url, type, provider) { - var options = getBaseRemoteOptions(); + const options = getBaseRemoteOptions(); options.Type = type; options.ImageUrl = url; @@ -136,9 +144,8 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image loading.show(); apiClient.downloadRemoteImage(options).then(function () { - hasChanges = true; - var dlg = dom.parentWithClass(page, 'dialog'); + const dlg = dom.parentWithClass(page, 'dialog'); dialogHelper.close(dlg); }); } @@ -148,17 +155,17 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } function getRemoteImageHtml(image, imageType, apiClient) { - var tagName = layoutManager.tv ? 'button' : 'div'; - var enableFooterButtons = !layoutManager.tv; + const tagName = layoutManager.tv ? 'button' : 'div'; + const enableFooterButtons = !layoutManager.tv; // TODO move card creation code to Card component - var html = ''; + let html = ''; - var cssClass = 'card scalableCard imageEditorCard'; - var cardBoxCssClass = 'cardBox visualCardBox'; + let cssClass = 'card scalableCard imageEditorCard'; + const cardBoxCssClass = 'cardBox visualCardBox'; - var shape = 'backdrop'; + let shape; if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') { shape = 'backdrop'; } else if (imageType === 'Banner') { @@ -166,7 +173,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } else if (imageType === 'Disc') { shape = 'square'; } else { - if (currentItemType === 'Episode') { shape = 'backdrop'; } else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') { @@ -217,19 +223,16 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image html += '
' + image.ProviderName + '
'; if (image.Width || image.Height || image.Language) { - html += '
'; if (image.Width && image.Height) { html += image.Width + ' x ' + image.Height; if (image.Language) { - html += ' • ' + image.Language; } } else { if (image.Language) { - html += image.Language; } } @@ -238,13 +241,11 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } if (image.CommunityRating != null) { - html += '
'; if (image.RatingType === 'Likes') { html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes'); } else { - if (image.CommunityRating) { html += image.CommunityRating.toFixed(1); @@ -270,7 +271,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image // end footer html += '
'; - //html += '
'; html += ''; @@ -287,7 +287,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image }); page.querySelector('#selectImageProvider').addEventListener('change', function () { - browsableImageStartIndex = 0; selectedProvider = this.value; @@ -295,22 +294,20 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image }); page.querySelector('#chkAllLanguages').addEventListener('change', function () { - browsableImageStartIndex = 0; reloadBrowsableImages(page, apiClient); }); page.addEventListener('click', function (e) { - - var btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage'); + const btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage'); if (btnDownloadRemoteImage) { - var card = dom.parentWithClass(btnDownloadRemoteImage, 'card'); + const card = dom.parentWithClass(btnDownloadRemoteImage, 'card'); downloadRemoteImage(page, apiClient, card.getAttribute('data-imageurl'), card.getAttribute('data-imagetype'), card.getAttribute('data-imageprovider')); return; } - var btnImageCard = dom.parentWithClass(e.target, 'btnImageCard'); + const btnImageCard = dom.parentWithClass(e.target, 'btnImageCard'); if (btnImageCard) { downloadRemoteImage(page, apiClient, btnImageCard.getAttribute('data-imageurl'), btnImageCard.getAttribute('data-imagetype'), btnImageCard.getAttribute('data-imageprovider')); } @@ -321,13 +318,12 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image loading.show(); require(['text!./imageDownloader.template.html'], function (template) { - - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); currentItemId = itemId; currentItemType = itemType; - var dialogOptions = { + const dialogOptions = { removeOnClose: true }; @@ -337,9 +333,9 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image dialogOptions.size = 'small'; } - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); - dlg.innerHTML = globalize.translateDocument(template, 'core'); + dlg.innerHTML = globalize.translateHtml(template, 'core'); if (layoutManager.tv) { scrollHelper.centerFocus.on(dlg, false); @@ -350,11 +346,10 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image dialogHelper.open(dlg); - var editorContent = dlg.querySelector('.formDialogContent'); + const editorContent = dlg.querySelector('.formDialogContent'); initEditor(editorContent, apiClient); dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); }); @@ -363,7 +358,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } function onDialogClosed() { - var dlg = this; + const dlg = this; if (layoutManager.tv) { scrollHelper.centerFocus.off(dlg, false); @@ -377,18 +372,20 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image } } - return { - show: function (itemId, serverId, itemType, imageType) { - return new Promise(function (resolve, reject) { - currentResolve = resolve; - currentReject = reject; - hasChanges = false; - browsableImageStartIndex = 0; - browsableImageType = imageType || 'Primary'; - selectedProvider = null; +export function show(itemId, serverId, itemType, imageType) { + return new Promise(function (resolve, reject) { + currentResolve = resolve; + currentReject = reject; + hasChanges = false; + browsableImageStartIndex = 0; + browsableImageType = imageType || 'Primary'; + selectedProvider = null; + showEditor(itemId, serverId, itemType); + }); +} - showEditor(itemId, serverId, itemType); - }); - } - }; -}); +export default { + show: show +}; + +/* eslint-enable indent */ diff --git a/src/components/imageOptionsEditor/imageOptionsEditor.js b/src/components/imageOptionsEditor/imageOptionsEditor.js index 257921dfa2..6660ecf74c 100644 --- a/src/components/imageOptionsEditor/imageOptionsEditor.js +++ b/src/components/imageOptionsEditor/imageOptionsEditor.js @@ -1,5 +1,16 @@ -define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) { - 'use strict'; +/* eslint-disable indent */ + +/** + * Module for image Options Editor. + * @module components/imageOptionsEditor/imageOptionsEditor + */ + +import globalize from 'globalize'; +import dom from 'dom'; +import dialogHelper from 'dialogHelper'; +import 'emby-checkbox'; +import 'emby-select'; +import 'emby-input'; function getDefaultImageConfig(itemType, type) { return { @@ -10,7 +21,7 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb } function findImageOptions(imageOptions, type) { - return imageOptions.filter(function (i) { + return imageOptions.filter(i => { return i.Type == type; })[0]; } @@ -31,14 +42,14 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb } function loadValues(context, itemType, options, availableOptions) { - var supportedImageTypes = availableOptions.SupportedImageTypes || []; - setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop')); - setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot')); - Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) { - var imageType = i.getAttribute('data-imagetype'); - var container = dom.parentWithTag(i, 'LABEL'); + const supportedImageTypes = availableOptions.SupportedImageTypes || []; + setVisibilityOfBackdrops(context.querySelector('.backdropFields'), supportedImageTypes.includes('Backdrop')); + setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), supportedImageTypes.includes('Screenshot')); + Array.prototype.forEach.call(context.querySelectorAll('.imageType'), i => { + const imageType = i.getAttribute('data-imagetype'); + const container = dom.parentWithTag(i, 'LABEL'); - if (-1 == supportedImageTypes.indexOf(imageType)) { + if (!supportedImageTypes.includes(imageType)) { container.classList.add('hide'); } else { container.classList.remove('hide'); @@ -50,16 +61,16 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb i.checked = false; } }); - var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType); + const backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType); context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit; context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth; - var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType); + const screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType); context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit; context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth; } function saveValues(context, options) { - options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) { + options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), c => { return { Type: c.getAttribute('data-imagetype'), Limit: c.checked ? 1 : 0, @@ -78,35 +89,36 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb }); } - function editor() { - this.show = function (itemType, options, availableOptions) { - return new Promise(function (resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', 'components/imageOptionsEditor/imageOptionsEditor.template.html', true); + async function showEditor(itemType, options, availableOptions) { + const response = await fetch('components/imageOptionsEditor/imageOptionsEditor.template.html'); + const template = await response.text(); - xhr.onload = function (e) { - var template = this.response; - var dlg = dialogHelper.createDialog({ - size: 'small', - removeOnClose: true, - scrollY: false - }); - dlg.classList.add('formDialog'); - dlg.innerHTML = globalize.translateDocument(template); - dlg.addEventListener('close', function () { - saveValues(dlg, options); - }); - loadValues(dlg, itemType, options, availableOptions); - dialogHelper.open(dlg).then(resolve, resolve); - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); - }; - - xhr.send(); - }); - }; + var dlg = dialogHelper.createDialog({ + size: 'small', + removeOnClose: true, + scrollY: false + }); + dlg.classList.add('formDialog'); + dlg.innerHTML = globalize.translateHtml(template); + dlg.addEventListener('close', function () { + saveValues(dlg, options); + }); + loadValues(dlg, itemType, options, availableOptions); + dialogHelper.open(dlg).then(() => { + return; + }).catch(() => { + return; + }); + dlg.querySelector('.btnCancel').addEventListener('click', function () { + dialogHelper.close(dlg); + }); } - return editor; -}); +export class editor { + constructor() { + this.show = showEditor; + } +} + +/* eslint-enable indent */ +export default editor; diff --git a/src/components/imageUploader/imageUploader.js b/src/components/imageUploader/imageUploader.js index 417bd94e11..59c31724d0 100644 --- a/src/components/imageUploader/imageUploader.js +++ b/src/components/imageUploader/imageUploader.js @@ -1,25 +1,40 @@ -define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', 'layoutManager', 'globalize', 'require', 'emby-button', 'emby-select', 'formDialogStyle', 'css!./style'], function (dialogHelper, connectionManager, dom, loading, scrollHelper, layoutManager, globalize, require) { - 'use strict'; +/* eslint-disable indent */ - var currentItemId; - var currentServerId; - var currentFile; - var hasChanges = false; +/** + * Module for imageUploader. + * @module components/imageUploader/imageUploader + */ + +import dialogHelper from 'dialogHelper'; +import connectionManager from 'connectionManager'; +import dom from 'dom'; +import loading from 'loading'; +import scrollHelper from 'scrollHelper'; +import layoutManager from 'layoutManager'; +import globalize from 'globalize'; +import 'emby-button'; +import 'emby-select'; +import 'formDialogStyle'; +import 'css!./style'; + + let currentItemId; + let currentServerId; + let currentFile; + let hasChanges = false; function onFileReaderError(evt) { - loading.hide(); switch (evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('MessageFileReadError')); }); break; case evt.target.error.ABORT_ERR: break; // noop default: - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('MessageFileReadError')); }); break; @@ -27,8 +42,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function setFiles(page, files) { - - var file = files[0]; + const file = files[0]; if (!file || !file.type.match('image.*')) { page.querySelector('#imageOutput').innerHTML = ''; @@ -39,23 +53,22 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' currentFile = file; - var reader = new FileReader(); + const reader = new FileReader(); reader.onerror = onFileReaderError; - reader.onloadstart = function () { + reader.onloadstart = () => { page.querySelector('#fldUpload').classList.add('hide'); }; - reader.onabort = function () { + reader.onabort = () => { loading.hide(); console.debug('File read cancelled'); }; // Closure to capture the file information. - reader.onload = (function (theFile) { - return function (e) { - + reader.onload = (theFile => { + return e => { // Render thumbnail. - var html = [''].join(''); + const html = [''].join(''); page.querySelector('#imageOutput').innerHTML = html; page.querySelector('#dropImageText').classList.add('hide'); @@ -68,15 +81,14 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function onSubmit(e) { - - var file = currentFile; + const file = currentFile; if (!file) { return false; } if (!file.type.startsWith('image/')) { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('MessageImageFileTypeAllowed')); }); e.preventDefault(); @@ -85,19 +97,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' loading.show(); - var dlg = dom.parentWithClass(this, 'dialog'); + const dlg = dom.parentWithClass(this, 'dialog'); - var imageType = dlg.querySelector('#selectImageType').value; + const imageType = dlg.querySelector('#selectImageType').value; if (imageType === 'None') { - require(['toast'], function(toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('MessageImageTypeNotSelected')); }); e.preventDefault(); return false; } - connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(function () { - + connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => { dlg.querySelector('#uploadImage').value = ''; loading.hide(); @@ -110,28 +121,25 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' } function initEditor(page) { - page.querySelector('form').addEventListener('submit', onSubmit); page.querySelector('#uploadImage').addEventListener('change', function () { setFiles(page, this.files); }); - page.querySelector('.btnBrowse').addEventListener('click', function () { + page.querySelector('.btnBrowse').addEventListener('click', () => { page.querySelector('#uploadImage').click(); }); } - function showEditor(options, resolve, reject) { - + function showEditor(options, resolve) { options = options || {}; - require(['text!./imageUploader.template.html'], function (template) { - + return import('text!./imageUploader.template.html').then(({default: template}) => { currentItemId = options.itemId; currentServerId = options.serverId; - var dialogOptions = { + const dialogOptions = { removeOnClose: true }; @@ -141,19 +149,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' dialogOptions.size = 'small'; } - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); - dlg.innerHTML = globalize.translateDocument(template, 'core'); + dlg.innerHTML = globalize.translateHtml(template, 'core'); if (layoutManager.tv) { scrollHelper.centerFocus.on(dlg, false); } // Has to be assigned a z-index after the call to .open() - dlg.addEventListener('close', function () { - + dlg.addEventListener('close', () => { if (layoutManager.tv) { scrollHelper.centerFocus.off(dlg, false); } @@ -168,22 +175,21 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', ' dlg.querySelector('#selectImageType').value = options.imageType || 'Primary'; - dlg.querySelector('.btnCancel').addEventListener('click', function () { - + dlg.querySelector('.btnCancel').addEventListener('click', () => { dialogHelper.close(dlg); }); }); } - return { - show: function (options) { + export function show(options) { + return new Promise(resolve => { + hasChanges = false; - return new Promise(function (resolve, reject) { + showEditor(options, resolve); + }); + } - hasChanges = false; - - showEditor(options, resolve, reject); - }); - } - }; -}); +/* eslint-enable indent */ +export default { + show: show +}; diff --git a/src/components/imageeditor/imageeditor.js b/src/components/imageeditor/imageeditor.js index 2927a0b120..78c35bb15f 100644 --- a/src/components/imageeditor/imageeditor.js +++ b/src/components/imageeditor/imageeditor.js @@ -1,14 +1,29 @@ -define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', 'focusManager', 'globalize', 'scrollHelper', 'imageLoader', 'require', 'browser', 'apphost', 'cardStyle', 'formDialogStyle', 'emby-button', 'paper-icon-button-light', 'css!./imageeditor'], function (dialogHelper, connectionManager, loading, dom, layoutManager, focusManager, globalize, scrollHelper, imageLoader, require, browser, appHost) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import connectionManager from 'connectionManager'; +import loading from 'loading'; +import dom from 'dom'; +import layoutManager from 'layoutManager'; +import focusManager from 'focusManager'; +import globalize from 'globalize'; +import scrollHelper from 'scrollHelper'; +import imageLoader from 'imageLoader'; +import browser from 'browser'; +import appHost from 'apphost'; +import 'cardStyle'; +import 'formDialogStyle'; +import 'emby-button'; +import 'paper-icon-button-light'; +import 'css!./imageeditor'; - var enableFocusTransform = !browser.slow && !browser.edge; +/* eslint-disable indent */ - var currentItem; - var hasChanges = false; + const enableFocusTransform = !browser.slow && !browser.edge; + + let currentItem; + let hasChanges = false; function getBaseRemoteOptions() { - - var options = {}; + const options = {}; options.itemId = currentItem.Id; @@ -16,16 +31,14 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function reload(page, item, focusContext) { - loading.show(); - var apiClient; + let apiClient; if (item) { apiClient = connectionManager.getApiClient(item.ServerId); reloadItem(page, item, apiClient, focusContext); } else { - apiClient = connectionManager.getApiClient(currentItem.ServerId); apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) { reloadItem(page, item, apiClient, focusContext); @@ -34,9 +47,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function addListeners(container, className, eventName, fn) { - container.addEventListener(eventName, function (e) { - var elem = dom.parentWithClass(e.target, className); + const elem = dom.parentWithClass(e.target, className); if (elem) { fn.call(elem, e); } @@ -44,14 +56,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function reloadItem(page, item, apiClient, focusContext) { - currentItem = item; apiClient.getRemoteImageProviders(getBaseRemoteOptions()).then(function (providers) { - - var btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages'); - for (var i = 0, length = btnBrowseAllImages.length; i < length; i++) { - + const btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages'); + for (let i = 0, length = btnBrowseAllImages.length; i < length; i++) { if (providers.length) { btnBrowseAllImages[i].classList.remove('hide'); } else { @@ -60,7 +69,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } apiClient.getItemImageInfos(currentItem.Id).then(function (imageInfos) { - renderStandardImages(page, apiClient, item, imageInfos, providers); renderBackdrops(page, apiClient, item, imageInfos, providers); renderScreenshots(page, apiClient, item, imageInfos, providers); @@ -74,7 +82,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function getImageUrl(item, apiClient, type, index, options) { - options = options || {}; options.type = type; options.index = index; @@ -94,13 +101,12 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function getCardHtml(image, index, numImages, apiClient, imageProviders, imageSize, tagName, enableFooterButtons) { - // TODO move card creation code to Card component - var html = ''; + let html = ''; - var cssClass = 'card scalableCard imageEditorCard'; - var cardBoxCssClass = 'cardBox visualCardBox'; + let cssClass = 'card scalableCard imageEditorCard'; + const cardBoxCssClass = 'cardBox visualCardBox'; cssClass += ' backdropCard backdropCard-scalable'; @@ -130,7 +136,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', html += '
'; - var imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize }); + const imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize }); html += '
'; @@ -153,7 +159,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', html += '
'; if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') { - if (index > 0) { html += ''; } else { @@ -183,13 +188,10 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function deleteImage(context, itemId, type, index, apiClient, enableConfirmation) { - - var afterConfirm = function () { + const afterConfirm = function () { apiClient.deleteItemImage(itemId, type, index).then(function () { - hasChanges = true; reload(context); - }); }; @@ -198,8 +200,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', return; } - require(['confirm'], function (confirm) { - + import('confirm').then(({default: confirm}) => { confirm({ text: globalize.translate('ConfirmDeleteImage'), @@ -211,36 +212,30 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function moveImage(context, apiClient, itemId, type, index, newIndex, focusContext) { - apiClient.updateItemImageIndex(itemId, type, index, newIndex).then(function () { - hasChanges = true; reload(context, null, focusContext); }, function () { - - require(['alert'], function (alert) { + import('alert').then(({default: alert}) => { alert(globalize.translate('DefaultErrorMessage')); }); }); } function renderImages(page, item, apiClient, images, imageProviders, elem) { + let html = ''; - var html = ''; - - var imageSize = 300; - var windowSize = dom.getWindowSize(); + let imageSize = 300; + const windowSize = dom.getWindowSize(); if (windowSize.innerWidth >= 1280) { imageSize = Math.round(windowSize.innerWidth / 4); } - var tagName = layoutManager.tv ? 'button' : 'div'; - var enableFooterButtons = !layoutManager.tv; - - for (var i = 0, length = images.length; i < length; i++) { - - var image = images[i]; + const tagName = layoutManager.tv ? 'button' : 'div'; + const enableFooterButtons = !layoutManager.tv; + for (let i = 0, length = images.length; i < length; i++) { + const image = images[i]; html += getCardHtml(image, i, length, apiClient, imageProviders, imageSize, tagName, enableFooterButtons); } @@ -249,8 +244,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) { - - var images = imageInfos.filter(function (i) { + const images = imageInfos.filter(function (i) { return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter'; }); @@ -258,10 +252,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) { - - var images = imageInfos.filter(function (i) { + const images = imageInfos.filter(function (i) { return i.ImageType === 'Backdrop'; - }).sort(function (a, b) { return a.ImageIndex - b.ImageIndex; }); @@ -275,10 +267,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) { - - var images = imageInfos.filter(function (i) { + const images = imageInfos.filter(function (i) { return i.ImageType === 'Screenshot'; - }).sort(function (a, b) { return a.ImageIndex - b.ImageIndex; }); @@ -292,32 +282,26 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } function showImageDownloader(page, imageType) { - - require(['imageDownloader'], function (ImageDownloader) { - + import('imageDownloader').then(({default: ImageDownloader}) => { ImageDownloader.show(currentItem.Id, currentItem.ServerId, currentItem.Type, imageType).then(function () { - hasChanges = true; reload(page); }); - }); } function showActionSheet(context, imageCard) { + const itemId = imageCard.getAttribute('data-id'); + const serverId = imageCard.getAttribute('data-serverid'); + const apiClient = connectionManager.getApiClient(serverId); - var itemId = imageCard.getAttribute('data-id'); - var serverId = imageCard.getAttribute('data-serverid'); - var apiClient = connectionManager.getApiClient(serverId); + const type = imageCard.getAttribute('data-imagetype'); + const index = parseInt(imageCard.getAttribute('data-index')); + const providerCount = parseInt(imageCard.getAttribute('data-providers')); + const numImages = parseInt(imageCard.getAttribute('data-numimages')); - var type = imageCard.getAttribute('data-imagetype'); - var index = parseInt(imageCard.getAttribute('data-index')); - var providerCount = parseInt(imageCard.getAttribute('data-providers')); - var numImages = parseInt(imageCard.getAttribute('data-numimages')); - - require(['actionsheet'], function (actionSheet) { - - var commands = []; + import('actionsheet').then(({default: actionSheet}) => { + const commands = []; commands.push({ name: globalize.translate('Delete'), @@ -353,9 +337,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', positionTo: imageCard }).then(function (id) { - switch (id) { - case 'delete': deleteImage(context, itemId, type, index, apiClient, false); break; @@ -371,16 +353,14 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', default: break; } - }); }); } function initEditor(context, options) { - - var uploadButtons = context.querySelectorAll('.btnOpenUploadMenu'); - var isFileInputSupported = appHost.supports('fileinput'); - for (var i = 0, length = uploadButtons.length; i < length; i++) { + const uploadButtons = context.querySelectorAll('.btnOpenUploadMenu'); + const isFileInputSupported = appHost.supports('fileinput'); + for (let i = 0, length = uploadButtons.length; i < length; i++) { if (isFileInputSupported) { uploadButtons[i].classList.remove('hide'); } else { @@ -389,10 +369,9 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', } addListeners(context, 'btnOpenUploadMenu', 'click', function () { - var imageType = this.getAttribute('data-imagetype'); - - require(['imageUploader'], function (imageUploader) { + const imageType = this.getAttribute('data-imagetype'); + import('imageUploader').then(({default: imageUploader}) => { imageUploader.show({ theme: options.theme, @@ -401,7 +380,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', serverId: currentItem.ServerId }).then(function (hasChanged) { - if (hasChanged) { hasChanges = true; reload(context); @@ -423,34 +401,32 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', }); addListeners(context, 'btnDeleteImage', 'click', function () { - var type = this.getAttribute('data-imagetype'); - var index = this.getAttribute('data-index'); + const type = this.getAttribute('data-imagetype'); + let index = this.getAttribute('data-index'); index = index === 'null' ? null : parseInt(index); - var apiClient = connectionManager.getApiClient(currentItem.ServerId); + const apiClient = connectionManager.getApiClient(currentItem.ServerId); deleteImage(context, currentItem.Id, type, index, apiClient, true); }); addListeners(context, 'btnMoveImage', 'click', function () { - var type = this.getAttribute('data-imagetype'); - var index = this.getAttribute('data-index'); - var newIndex = this.getAttribute('data-newindex'); - var apiClient = connectionManager.getApiClient(currentItem.ServerId); + const type = this.getAttribute('data-imagetype'); + const index = this.getAttribute('data-index'); + const newIndex = this.getAttribute('data-newindex'); + const apiClient = connectionManager.getApiClient(currentItem.ServerId); moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer')); }); } function showEditor(options, resolve, reject) { - - var itemId = options.itemId; - var serverId = options.serverId; + const itemId = options.itemId; + const serverId = options.serverId; loading.show(); - require(['text!./imageeditor.template.html'], function (template) { - var apiClient = connectionManager.getApiClient(serverId); + import('text!./imageeditor.template.html').then(({default: template}) => { + const apiClient = connectionManager.getApiClient(serverId); apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { - - var dialogOptions = { + const dialogOptions = { removeOnClose: true }; @@ -460,11 +436,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', dialogOptions.size = 'small'; } - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); - dlg.innerHTML = globalize.translateDocument(template, 'core'); + dlg.innerHTML = globalize.translateHtml(template, 'core'); if (layoutManager.tv) { scrollHelper.centerFocus.on(dlg, false); @@ -474,7 +450,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', // Has to be assigned a z-index after the call to .open() dlg.addEventListener('close', function () { - if (layoutManager.tv) { scrollHelper.centerFocus.off(dlg, false); } @@ -493,22 +468,21 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', reload(dlg, item); dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); }); }); }); } - return { - show: function (options) { +export function show (options) { + return new Promise(function (resolve, reject) { + hasChanges = false; + showEditor(options, resolve, reject); + }); +} - return new Promise(function (resolve, reject) { +export default { + show +}; - hasChanges = false; - - showEditor(options, resolve, reject); - }); - } - }; -}); +/* eslint-enable indent */ diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index a10805fdb4..c9d3e6fdb2 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -120,7 +120,7 @@ import 'css!./style'; export function lazyChildren(elem) { if (userSettings.enableBlurhash()) { - for (const lazyElem of elem.getElementsByClassName('lazy')) { + for (const lazyElem of elem.querySelectorAll('.lazy')) { const blurhashstr = lazyElem.getAttribute('data-blurhash'); if (!lazyElem.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) { itemBlurhashing(lazyElem, blurhashstr); @@ -133,11 +133,9 @@ import 'css!./style'; } export function getPrimaryImageAspectRatio(items) { - var values = []; for (var i = 0, length = items.length; i < length; i++) { - var ratio = items[i].PrimaryImageAspectRatio || 0; if (!ratio) { @@ -193,7 +191,6 @@ import 'css!./style'; } export function fillImages(elems) { - for (var i = 0, length = elems.length; i < length; i++) { var elem = elems[0]; fillImage(elem); diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 96f8f2d356..173383d064 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -1,14 +1,22 @@ -define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) { - 'use strict'; +import appHost from 'apphost'; +import globalize from 'globalize'; +import connectionManager from 'connectionManager'; +import itemHelper from 'itemHelper'; +import appRouter from 'appRouter'; +import playbackManager from 'playbackManager'; +import browser from 'browser'; +import actionsheet from 'actionsheet'; - function getCommands(options) { - var item = options.item; - var user = options.user; +/* eslint-disable indent */ - var canPlay = playbackManager.canPlay(item); - var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator; + export function getCommands(options) { + const item = options.item; + const user = options.user; - var commands = []; + const canPlay = playbackManager.canPlay(item); + const restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator; + + let commands = []; if (canPlay && item.MediaType !== 'Photo') { if (options.play !== false) { @@ -134,7 +142,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } if (item.CanDelete && options.deleteItem !== false) { - if (item.Type === 'Playlist' || item.Type === 'BoxSet') { commands.push({ name: globalize.translate('Delete'), @@ -171,10 +178,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); } - var canEdit = itemHelper.canEdit(user, item); + const canEdit = itemHelper.canEdit(user, item); if (canEdit) { if (options.edit !== false && item.Type !== 'SeriesTimer') { - var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); + const text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); commands.push({ name: text, id: 'edit', @@ -322,31 +329,31 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function executeCommand(item, id, options) { - var itemId = item.Id; - var serverId = item.ServerId; - var apiClient = connectionManager.getApiClient(serverId); + const itemId = item.Id; + const serverId = item.ServerId; + const apiClient = connectionManager.getApiClient(serverId); return new Promise(function (resolve, reject) { switch (id) { case 'addtocollection': - require(['collectionEditor'], function (collectionEditor) { - new collectionEditor().show({ + import('collectionEditor').then(({default: collectionEditor}) => { + new collectionEditor({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; case 'addtoplaylist': - require(['playlistEditor'], function (playlistEditor) { - new playlistEditor().show({ + import('playlistEditor').then(({default: playlistEditor}) => { + new playlistEditor({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; case 'download': - require(['fileDownloader'], function (fileDownloader) { - var downloadHref = apiClient.getItemDownloadUrl(itemId); + import('fileDownloader').then((fileDownloader) => { + const downloadHref = apiClient.getItemDownloadUrl(itemId); fileDownloader.download([{ url: downloadHref, itemId: itemId, @@ -357,17 +364,17 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', getResolveFunction(getResolveFunction(resolve, id), id)(); }); break; - case 'copy-stream': - var downloadHref = apiClient.getItemDownloadUrl(itemId); - var textAreaCopy = function () { - var textArea = document.createElement('textarea'); + case 'copy-stream': { + const downloadHref = apiClient.getItemDownloadUrl(itemId); + const textAreaCopy = function () { + let textArea = document.createElement('textarea'); textArea.value = downloadHref; document.body.appendChild(textArea); textArea.focus(); textArea.select(); if (document.execCommand('copy')) { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('CopyStreamURLSuccess')); }); } else { @@ -382,7 +389,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } else { /* eslint-disable-next-line compat/compat */ navigator.clipboard.writeText(downloadHref).then(function () { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('CopyStreamURLSuccess')); }); }).catch(function () { @@ -391,8 +398,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } getResolveFunction(resolve, id)(); break; + } case 'editsubtitles': - require(['subtitleEditor'], function (subtitleEditor) { + import('subtitleEditor').then(({default: subtitleEditor}) => { subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; @@ -400,7 +408,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); break; case 'editimages': - require(['imageEditor'], function (imageEditor) { + import('imageEditor').then(({default: imageEditor}) => { imageEditor.show({ itemId: itemId, serverId: serverId @@ -408,12 +416,12 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); break; case 'identify': - require(['itemIdentifier'], function (itemIdentifier) { + import('itemIdentifier').then(({default: itemIdentifier}) => { itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; case 'moremediainfo': - require(['itemMediaInfo'], function (itemMediaInfo) { + import('itemMediaInfo').then(({default: itemMediaInfo}) => { itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id)); }); break; @@ -448,7 +456,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', playbackManager.clearQueue(); break; case 'record': - require(['recordingCreator'], function (recordingCreator) { + import('recordingCreator').then(({default: recordingCreator}) => { recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }); break; @@ -519,8 +527,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function deleteTimer(apiClient, item, resolve, command) { - require(['recordingHelper'], function (recordingHelper) { - var timerId = item.TimerId || item.Id; + import('recordingHelper').then(({default: recordingHelper}) => { + const timerId = item.TimerId || item.Id; recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); }); @@ -528,7 +536,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function deleteSeriesTimer(apiClient, item, resolve, command) { - require(['recordingHelper'], function (recordingHelper) { + import('recordingHelper').then(({default: recordingHelper}) => { recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () { getResolveFunction(resolve, command, true)(); }); @@ -536,9 +544,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function play(item, resume, queue, queueNext) { - var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play'; + const method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play'; - var startPosition = 0; + let startPosition = 0; if (resume && item.UserData && item.UserData.PlaybackPositionTicks) { startPosition = item.UserData.PlaybackPositionTicks; } @@ -559,18 +567,18 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', function editItem(apiClient, item) { return new Promise(function (resolve, reject) { - var serverId = apiClient.serverInfo().Id; + const serverId = apiClient.serverInfo().Id; if (item.Type === 'Timer') { - require(['recordingEditor'], function (recordingEditor) { + import('recordingEditor').then(({default: recordingEditor}) => { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } else if (item.Type === 'SeriesTimer') { - require(['seriesRecordingEditor'], function (recordingEditor) { + import('seriesRecordingEditor').then(({default: recordingEditor}) => { recordingEditor.show(item.Id, serverId).then(resolve, reject); }); } else { - require(['metadataEditor'], function (metadataEditor) { + import('metadataEditor').then(({default: metadataEditor}) => { metadataEditor.show(item.Id, serverId).then(resolve, reject); }); } @@ -579,7 +587,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', function deleteItem(apiClient, item) { return new Promise(function (resolve, reject) { - require(['deleteHelper'], function (deleteHelper) { + import('deleteHelper').then(({default: deleteHelper}) => { deleteHelper.deleteItem({ item: item, navigate: false @@ -591,7 +599,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', } function refresh(apiClient, item) { - require(['refreshDialog'], function (refreshDialog) { + import('refreshDialog').then(({default: refreshDialog}) => { new refreshDialog({ itemIds: [item.Id], serverId: apiClient.serverInfo().Id, @@ -600,8 +608,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); } - function show(options) { - var commands = getCommands(options); + export function show(options) { + const commands = getCommands(options); if (!commands.length) { return Promise.reject(); } @@ -615,8 +623,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', }); } - return { - getCommands: getCommands, - show: show - }; -}); +/* eslint-enable indent */ + +export default { + getCommands: getCommands, + show: show +}; diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index 3508866bdb..55e9e10062 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -2,7 +2,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { 'use strict'; function getDisplayName(item, options = {}) { - if (!item) { throw new Error('null item passed into getDisplayName'); } @@ -22,7 +21,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { if (item.Type === 'Episode' && item.ParentIndexNumber === 0) { name = globalize.translate('ValueSpecialEpisodeName', name); } else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) { - var displayIndexNumber = item.IndexNumber; var number = displayIndexNumber; @@ -35,7 +33,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { } if (item.IndexNumberEnd) { - displayIndexNumber = item.IndexNumberEnd; number += '-' + displayIndexNumber; } @@ -49,7 +46,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { } function supportsAddingToCollection(item) { - var invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer']; if (item.Type === 'Recording') { @@ -62,7 +58,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { } function supportsAddingToPlaylist(item) { - if (item.Type === 'Program') { return false; } @@ -96,7 +91,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { } function canEdit(user, item) { - var itemType = item.Type; if (itemType === 'UserRootFolder' || itemType === 'UserView') { @@ -129,7 +123,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { } function isLocalItem(item) { - if (item && item.Id && item.Id.indexOf('local') === 0) { return true; } @@ -144,7 +137,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { isLocalItem: isLocalItem, canIdentify: function (user, item) { - var itemType = item.Type; if (itemType === 'Movie' || @@ -156,9 +148,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) { itemType === 'MusicAlbum' || itemType === 'MusicArtist' || itemType === 'MusicVideo') { - if (user.Policy.IsAdministrator) { - if (!isLocalItem(item)) { return true; } @@ -171,7 +161,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { canEdit: canEdit, canEditImages: function (user, item) { - var itemType = item.Type; if (item.MediaType === 'Photo') { @@ -180,7 +169,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { if (itemType === 'UserView') { if (user.Policy.IsAdministrator) { - return true; } @@ -197,7 +185,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canSync: function (user, item) { - if (user && !user.Policy.EnableContentDownloading) { return false; } @@ -210,7 +197,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canShare: function (item, user) { - if (item.Type === 'Program') { return false; } @@ -239,7 +225,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canMarkPlayed: function (item) { - if (item.Type === 'Program') { return false; } @@ -269,7 +254,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canRate: function (item) { - if (item.Type === 'Program' || item.Type === 'Timer' || item.Type === 'SeriesTimer' @@ -284,7 +268,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canConvert: function (item, user) { - if (!user.Policy.EnableMediaConversion) { return false; } @@ -320,16 +303,13 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, canRefreshMetadata: function (item, user) { - if (user.Policy.IsAdministrator) { - var collectionType = item.CollectionType; if (collectionType === 'livetv') { return false; } if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { - if (!isLocalItem(item)) { return true; } @@ -340,7 +320,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) { }, supportsMediaSourceSelection: function (item) { - if (item.MediaType !== 'Video') { return false; } diff --git a/src/components/itemMediaInfo/itemMediaInfo.js b/src/components/itemMediaInfo/itemMediaInfo.js index 81c84b6a23..c3fd9e0d0a 100644 --- a/src/components/itemMediaInfo/itemMediaInfo.js +++ b/src/components/itemMediaInfo/itemMediaInfo.js @@ -1,44 +1,61 @@ -define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', 'connectionManager', 'loading', 'focusManager', 'dom', 'apphost', 'emby-select', 'listViewStyle', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'emby-button', 'flexStyles'], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) { - 'use strict'; +/* eslint-disable indent */ + +/** + * Module for display media info. + * @module components/itemMediaInfo/itemMediaInfo + */ + +import dialogHelper from 'dialogHelper'; +import layoutManager from 'layoutManager'; +import globalize from 'globalize'; +import connectionManager from 'connectionManager'; +import loading from 'loading'; +import 'emby-select'; +import 'listViewStyle'; +import 'paper-icon-button-light'; +import 'css!./../formdialog'; +import 'material-icons'; +import 'emby-button'; +import 'flexStyles'; function setMediaInfo(user, page, item) { - var html = item.MediaSources.map(function (version) { + let html = item.MediaSources.map(version => { return getMediaSourceHtml(user, item, version); }).join('
'); if (item.MediaSources.length > 1) { - html = '
' + html; + html = `
${html}`; } - var mediaInfoContent = page.querySelector('#mediaInfoContent'); + const mediaInfoContent = page.querySelector('#mediaInfoContent'); mediaInfoContent.innerHTML = html; } function getMediaSourceHtml(user, item, version) { - var html = ''; + let html = ''; if (version.Name) { - html += '

' + version.Name + '

'; + html += `

${version.Name}

`; } if (version.Container) { - html += createAttribute(globalize.translate('MediaInfoContainer'), version.Container) + '
'; + html += `${createAttribute(globalize.translate('MediaInfoContainer'), version.Container)}
`; } if (version.Formats && version.Formats.length) { - html += createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(',')) + '
'; + html += `${createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(','))}
`; } if (version.Path && user && user.Policy.IsAdministrator) { - html += createAttribute(globalize.translate('MediaInfoPath'), version.Path) + '
'; + html += `${createAttribute(globalize.translate('MediaInfoPath'), version.Path)}
`; } if (version.Size) { - var size = (version.Size / (1024 * 1024)).toFixed(0) + ' MB'; - html += createAttribute(globalize.translate('MediaInfoSize'), size) + '
'; + const size = `${(version.Size / (1024 * 1024)).toFixed(0)} MB`; + html += `${createAttribute(globalize.translate('MediaInfoSize'), size)}
`; } - for (var i = 0, length = version.MediaStreams.length; i < length; i++) { - var stream = version.MediaStreams[i]; + for (let i = 0, length = version.MediaStreams.length; i < length; i++) { + const stream = version.MediaStreams[i]; if (stream.Type === 'Data') { continue; } html += '
'; - var displayType = globalize.translate('MediaInfoStreamType' + stream.Type); - html += '

' + displayType + '

'; - var attributes = []; + const displayType = globalize.translate(`MediaInfoStreamType${stream.Type}`); + html += `

${displayType}

`; + const attributes = []; if (stream.DisplayTitle) { attributes.push(createAttribute('Title', stream.DisplayTitle)); } @@ -61,7 +78,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level)); } if (stream.Width || stream.Height) { - attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), stream.Width + 'x' + stream.Height)); + attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), `${stream.Width}x${stream.Height}`)); } if (stream.AspectRatio && stream.Codec !== 'mjpeg') { attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio)); @@ -79,16 +96,16 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout)); } if (stream.Channels) { - attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), stream.Channels + ' ch')); + attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), `${stream.Channels} ch`)); } if (stream.BitRate && stream.Codec !== 'mjpeg') { - attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), (parseInt(stream.BitRate / 1000)) + ' kbps')); + attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), `${parseInt(stream.BitRate / 1000)} kbps`)); } if (stream.SampleRate) { - attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), stream.SampleRate + ' Hz')); + attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), `${stream.SampleRate} Hz`)); } if (stream.BitDepth) { - attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit')); + attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), `${stream.BitDepth} bit`)); } if (stream.PixelFormat) { attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat)); @@ -116,13 +133,13 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', } function createAttribute(label, value) { - return '' + label + '' + value + ''; + return `${label}${value}`; } - function showMediaInfoMore(itemId, serverId, template) { - var apiClient = connectionManager.getApiClient(serverId); - return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { - var dialogOptions = { + function loadMediaInfo(itemId, serverId, template) { + const apiClient = connectionManager.getApiClient(serverId); + return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => { + const dialogOptions = { size: 'small', removeOnClose: true, scrollY: false @@ -130,35 +147,35 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', if (layoutManager.tv) { dialogOptions.size = 'fullscreen'; } - var dlg = dialogHelper.createDialog(dialogOptions); + const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); - var html = ''; - html += globalize.translateDocument(template, 'core'); + let html = ''; + html += globalize.translateHtml(template, 'core'); dlg.innerHTML = html; if (layoutManager.tv) { dlg.querySelector('.formDialogContent'); } dialogHelper.open(dlg); - dlg.querySelector('.btnCancel').addEventListener('click', function (e) { + dlg.querySelector('.btnCancel').addEventListener('click', () => { dialogHelper.close(dlg); }); - apiClient.getCurrentUser().then(function (user) { + apiClient.getCurrentUser().then(user => { setMediaInfo(user, dlg, item); }); loading.hide(); }); } - function showMediaInfo(itemId, serverId) { + export function show(itemId, serverId) { loading.show(); - return new Promise(function (resolve, reject) { - require(['text!./itemMediaInfo.template.html'], function (template) { - showMediaInfoMore(itemId, serverId, template).then(resolve, reject); + return import('text!./itemMediaInfo.template.html').then(({default: template}) => { + return new Promise((resolve, reject) => { + loadMediaInfo(itemId, serverId, template).then(resolve, reject); }); }); } - return { - show: showMediaInfo - }; -}); +/* eslint-enable indent */ +export default { + show: show +}; diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index 3399386394..5630680fbf 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -1,36 +1,52 @@ -define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', 'scrollHelper', 'layoutManager', 'focusManager', 'browser', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'cardStyle'], function (dialogHelper, loading, connectionManager, require, globalize, scrollHelper, layoutManager, focusManager, browser) { - 'use strict'; +/* eslint-disable indent */ - var enableFocusTransform = !browser.slow && !browser.edge; +/** + * Module for itemidentifier media item. + * @module components/itemidentifier/itemidentifier + */ - var currentItem; - var currentItemType; - var currentServerId; - var currentResolve; - var currentReject; - var hasChanges = false; - var currentSearchResult; +import dialogHelper from 'dialogHelper'; +import loading from 'loading'; +import connectionManager from 'connectionManager'; +import globalize from 'globalize'; +import scrollHelper from 'scrollHelper'; +import layoutManager from 'layoutManager'; +import focusManager from 'focusManager'; +import browser from 'browser'; +import 'emby-input'; +import 'emby-checkbox'; +import 'paper-icon-button-light'; +import 'css!./../formdialog'; +import 'material-icons'; +import 'cardStyle'; + + const enableFocusTransform = !browser.slow && !browser.edge; + + let currentItem; + let currentItemType; + let currentServerId; + let currentResolve; + let currentReject; + let hasChanges = false; + let currentSearchResult; function getApiClient() { return connectionManager.getApiClient(currentServerId); } function searchForIdentificationResults(page) { - - var lookupInfo = { + let lookupInfo = { ProviderIds: {} }; - var i; - var length; - var identifyField = page.querySelectorAll('.identifyField'); - var value; + let i; + let length; + const identifyField = page.querySelectorAll('.identifyField'); + let value; for (i = 0, length = identifyField.length; i < length; i++) { - value = identifyField[i].value; if (value) { - if (identifyField[i].type === 'number') { value = parseInt(value); } @@ -39,11 +55,10 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } } - var hasId = false; + let hasId = false; - var txtLookupId = page.querySelectorAll('.txtLookupId'); + const txtLookupId = page.querySelectorAll('.txtLookupId'); for (i = 0, length = txtLookupId.length; i < length; i++) { - value = txtLookupId[i].value; if (value) { @@ -53,7 +68,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } if (!hasId && !lookupInfo.Name) { - require(['toast'], function (toast) { + import('toast').then(({default: toast}) => { toast(globalize.translate('PleaseEnterNameOrId')); }); return; @@ -71,60 +86,54 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', loading.show(); - var apiClient = getApiClient(); + const apiClient = getApiClient(); apiClient.ajax({ type: 'POST', - url: apiClient.getUrl('Items/RemoteSearch/' + currentItemType), + url: apiClient.getUrl(`Items/RemoteSearch/${currentItemType}`), data: JSON.stringify(lookupInfo), contentType: 'application/json', dataType: 'json' - }).then(function (results) { - + }).then(results => { loading.hide(); showIdentificationSearchResults(page, results); }); } function showIdentificationSearchResults(page, results) { - - var identificationSearchResults = page.querySelector('.identificationSearchResults'); + const identificationSearchResults = page.querySelector('.identificationSearchResults'); page.querySelector('.popupIdentifyForm').classList.add('hide'); identificationSearchResults.classList.remove('hide'); page.querySelector('.identifyOptionsForm').classList.add('hide'); page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered'); - var html = ''; - var i; - var length; + let html = ''; + let i; + let length; for (i = 0, length = results.length; i < length; i++) { - - var result = results[i]; + const result = results[i]; html += getSearchResultHtml(result, i); } - var elem = page.querySelector('.identificationSearchResultList'); + const elem = page.querySelector('.identificationSearchResultList'); elem.innerHTML = html; function onSearchImageClick() { - var index = parseInt(this.getAttribute('data-index')); + const index = parseInt(this.getAttribute('data-index')); - var currentResult = results[index]; + const currentResult = results[index]; if (currentItem != null) { - showIdentifyOptions(page, currentResult); } else { - finishFindNewDialog(page, currentResult); } } - var searchImages = elem.querySelectorAll('.card'); + const searchImages = elem.querySelectorAll('.card'); for (i = 0, length = searchImages.length; i < length; i++) { - searchImages[i].addEventListener('click', onSearchImageClick); } @@ -142,8 +151,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } function showIdentifyOptions(page, identifyResult) { - - var identifyOptionsForm = page.querySelector('.identifyOptionsForm'); + const identifyOptionsForm = page.querySelector('.identifyOptionsForm'); page.querySelector('.popupIdentifyForm').classList.add('hide'); page.querySelector('.identificationSearchResults').classList.add('hide'); @@ -153,19 +161,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', currentSearchResult = identifyResult; - var lines = []; + const lines = []; lines.push(identifyResult.Name); if (identifyResult.ProductionYear) { lines.push(identifyResult.ProductionYear); } - var resultHtml = lines.join('
'); + let resultHtml = lines.join('
'); if (identifyResult.ImageUrl) { - var displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName); + const displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName); - resultHtml = '
' + resultHtml + '
'; + resultHtml = `
${resultHtml}
`; } page.querySelector('.selectedSearchResult').innerHTML = resultHtml; @@ -174,13 +182,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', } function getSearchResultHtml(result, index) { - // TODO move card creation code to Card component - var html = ''; - var cssClass = 'card scalableCard'; - var cardBoxCssClass = 'cardBox'; - var padderClass; + let html = ''; + let cssClass = 'card scalableCard'; + let cardBoxCssClass = 'cardBox'; + let padderClass; if (currentItemType === 'Episode') { cssClass += ' backdropCard backdropCard-scalable'; @@ -203,30 +210,29 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', cardBoxCssClass += ' cardBox-bottompadded'; - html += ''; + html += ``; } else if (plugins.length > 1) { - html += ''; + html += ``; } html += '
'; } html += '
'; - html += '
' + globalize.translate('LabelMetadataReadersHelp') + '
'; + html += `
${globalize.translate('LabelMetadataReadersHelp')}
`; if (plugins.length < 2) { elem.classList.add('hide'); } else { @@ -83,25 +93,25 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function renderMetadataSavers(page, metadataSavers) { - var html = ''; - var elem = page.querySelector('.metadataSavers'); + let html = ''; + const elem = page.querySelector('.metadataSavers'); if (!metadataSavers.length) return elem.innerHTML = '', elem.classList.add('hide'), false; - html += '

' + globalize.translate('LabelMetadataSavers') + '

'; + html += `

${globalize.translate('LabelMetadataSavers')}

`; html += '
'; - for (var i = 0; i < metadataSavers.length; i++) { - var plugin = metadataSavers[i]; - html += ''; + for (let i = 0; i < metadataSavers.length; i++) { + const plugin = metadataSavers[i]; + html += ``; } html += '
'; - html += '
' + globalize.translate('LabelMetadataSaversHelp') + '
'; + html += `
${globalize.translate('LabelMetadataSaversHelp')}
`; elem.innerHTML = html; elem.classList.remove('hide'); return true; } function getMetadataFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) { - var html = ''; - var plugins = availableTypeOptions.MetadataFetchers; + let html = ''; + let plugins = availableTypeOptions.MetadataFetchers; plugins = getOrderedPlugins(plugins, libraryOptionsForType.MetadataFetcherOrder || []); if (!plugins.length) return html; @@ -112,8 +122,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct plugins.forEach((plugin, index) => { html += '
'; - var isChecked = libraryOptionsForType.MetadataFetchers ? -1 !== libraryOptionsForType.MetadataFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; - var checkedHtml = isChecked ? ' checked="checked"' : ''; + const isChecked = libraryOptionsForType.MetadataFetchers ? libraryOptionsForType.MetadataFetchers.includes(plugin.Name) : plugin.DefaultEnabled; + const checkedHtml = isChecked ? ' checked="checked"' : ''; html += ''; html += '
'; html += '

'; @@ -135,19 +145,19 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function getTypeOptions(allOptions, type) { - var allTypeOptions = allOptions.TypeOptions || []; - for (var i = 0; i < allTypeOptions.length; i++) { - var typeOptions = allTypeOptions[i]; + const allTypeOptions = allOptions.TypeOptions || []; + for (let i = 0; i < allTypeOptions.length; i++) { + const typeOptions = allTypeOptions[i]; if (typeOptions.Type === type) return typeOptions; } return null; } function renderMetadataFetchers(page, availableOptions, libraryOptions) { - var html = ''; - var elem = page.querySelector('.metadataFetchers'); - for (var i = 0; i < availableOptions.TypeOptions.length; i++) { - var availableTypeOptions = availableOptions.TypeOptions[i]; + let html = ''; + const elem = page.querySelector('.metadataFetchers'); + for (let i = 0; i < availableOptions.TypeOptions.length; i++) { + const availableTypeOptions = availableOptions.TypeOptions[i]; html += getMetadataFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {}); } elem.innerHTML = html; @@ -166,41 +176,41 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function renderSubtitleFetchers(page, availableOptions, libraryOptions) { - var html = ''; - var elem = page.querySelector('.subtitleFetchers'); + let html = ''; + const elem = page.querySelector('.subtitleFetchers'); - var plugins = availableOptions.SubtitleFetchers; + let plugins = availableOptions.SubtitleFetchers; plugins = getOrderedPlugins(plugins, libraryOptions.SubtitleFetcherOrder || []); if (!plugins.length) return html; - html += '

' + globalize.translate('LabelSubtitleDownloaders') + '

'; + html += `

${globalize.translate('LabelSubtitleDownloaders')}

`; html += '
'; - for (var i = 0; i < plugins.length; i++) { - var plugin = plugins[i]; - html += '
'; - var isChecked = libraryOptions.DisabledSubtitleFetchers ? -1 === libraryOptions.DisabledSubtitleFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; - var checkedHtml = isChecked ? ' checked="checked"' : ''; - html += ''; + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i]; + html += `
`; + const isChecked = libraryOptions.DisabledSubtitleFetchers ? !libraryOptions.DisabledSubtitleFetchers.includes(plugin.Name) : plugin.DefaultEnabled; + const checkedHtml = isChecked ? ' checked="checked"' : ''; + html += ``; html += '
'; html += '

'; html += plugin.Name; html += '

'; html += '
'; if (i > 0) { - html += ''; + html += ``; } else if (plugins.length > 1) { - html += ''; + html += ``; } html += '
'; } html += '
'; - html += '
' + globalize.translate('SubtitleDownloadersHelp') + '
'; + html += `
${globalize.translate('SubtitleDownloadersHelp')}
`; elem.innerHTML = html; } function getImageFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) { - var html = ''; - var plugins = availableTypeOptions.ImageFetchers; + let html = ''; + let plugins = availableTypeOptions.ImageFetchers; plugins = getOrderedPlugins(plugins, libraryOptionsForType.ImageFetcherOrder || []); if (!plugins.length) return html; @@ -208,17 +218,17 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct html += '
'; html += '
'; html += '

' + globalize.translate('HeaderTypeImageFetchers', availableTypeOptions.Type) + '

'; - var supportedImageTypes = availableTypeOptions.SupportedImageTypes || []; + const supportedImageTypes = availableTypeOptions.SupportedImageTypes || []; if (supportedImageTypes.length > 1 || 1 === supportedImageTypes.length && 'Primary' !== supportedImageTypes[0]) { html += ''; } html += '
'; html += '
'; - for (var i = 0; i < plugins.length; i++) { - var plugin = plugins[i]; + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i]; html += '
'; - var isChecked = libraryOptionsForType.ImageFetchers ? -1 !== libraryOptionsForType.ImageFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; - var checkedHtml = isChecked ? ' checked="checked"' : ''; + const isChecked = libraryOptionsForType.ImageFetchers ? libraryOptionsForType.ImageFetchers.includes(plugin.Name) : plugin.DefaultEnabled; + const checkedHtml = isChecked ? ' checked="checked"' : ''; html += ''; html += '
'; html += '

'; @@ -239,10 +249,10 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function renderImageFetchers(page, availableOptions, libraryOptions) { - var html = ''; - var elem = page.querySelector('.imageFetchers'); - for (var i = 0; i < availableOptions.TypeOptions.length; i++) { - var availableTypeOptions = availableOptions.TypeOptions[i]; + let html = ''; + const elem = page.querySelector('.imageFetchers'); + for (let i = 0; i < availableOptions.TypeOptions.length; i++) { + const availableTypeOptions = availableOptions.TypeOptions[i]; html += getImageFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {}); } elem.innerHTML = html; @@ -258,12 +268,12 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct return true; } - function populateMetadataSettings(parent, contentType, isNewLibrary) { - var isNewLibrary = parent.classList.contains('newlibrary'); + function populateMetadataSettings(parent, contentType) { + const isNewLibrary = parent.classList.contains('newlibrary'); return ApiClient.getJSON(ApiClient.getUrl('Libraries/AvailableOptions', { LibraryContentType: contentType, IsNewLibrary: isNewLibrary - })).then(function(availableOptions) { + })).then(availableOptions => { currentAvailableOptions = availableOptions; parent.availableOptions = availableOptions; renderMetadataSavers(parent, availableOptions.MetadataSavers); @@ -272,14 +282,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct renderSubtitleFetchers(parent, availableOptions, {}); renderImageFetchers(parent, availableOptions, {}); availableOptions.SubtitleFetchers.length ? parent.querySelector('.subtitleDownloadSettings').classList.remove('hide') : parent.querySelector('.subtitleDownloadSettings').classList.add('hide'); - }).catch(function() { + }).catch(() => { return Promise.resolve(); }); } function adjustSortableListElement(elem) { - var btnSortable = elem.querySelector('.btnSortable'); - var inner = btnSortable.querySelector('.material-icons'); + const btnSortable = elem.querySelector('.btnSortable'); + const inner = btnSortable.querySelector('.material-icons'); if (elem.previousSibling) { btnSortable.title = globalize.translate('ButtonUp'); btnSortable.classList.add('btnSortableMoveUp'); @@ -296,22 +306,22 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function showImageOptionsForType(type) { - require(['imageoptionseditor'], function(ImageOptionsEditor) { - var typeOptions = getTypeOptions(currentLibraryOptions, type); + import('imageoptionseditor').then(({default: ImageOptionsEditor}) => { + let typeOptions = getTypeOptions(currentLibraryOptions, type); if (!typeOptions) { typeOptions = { Type: type }; currentLibraryOptions.TypeOptions.push(typeOptions); } - var availableOptions = getTypeOptions(currentAvailableOptions || {}, type); - var imageOptionsEditor = new ImageOptionsEditor(); + const availableOptions = getTypeOptions(currentAvailableOptions || {}, type); + const imageOptionsEditor = new ImageOptionsEditor(); imageOptionsEditor.show(type, typeOptions, availableOptions); }); } function onImageFetchersContainerClick(e) { - var btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType'); + const btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType'); if (btnImageOptionsForType) { return void showImageOptionsForType(dom.parentWithClass(btnImageOptionsForType, 'imageFetcher').getAttribute('data-type')); } @@ -319,18 +329,18 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function onSortableContainerClick(e) { - var btnSortable = dom.parentWithClass(e.target, 'btnSortable'); + const btnSortable = dom.parentWithClass(e.target, 'btnSortable'); if (btnSortable) { - var li = dom.parentWithClass(btnSortable, 'sortableOption'); - var list = dom.parentWithClass(li, 'paperList'); + const li = dom.parentWithClass(btnSortable, 'sortableOption'); + const list = dom.parentWithClass(li, 'paperList'); if (btnSortable.classList.contains('btnSortableMoveDown')) { - var next = li.nextSibling; + const next = li.nextSibling; if (next) { li.parentNode.removeChild(li); next.parentNode.insertBefore(li, next.nextSibling); } } else { - var prev = li.previousSibling; + const prev = li.previousSibling; if (prev) { li.parentNode.removeChild(li); prev.parentNode.insertBefore(li, prev); @@ -347,41 +357,35 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct parent.querySelector('.imageFetchers').addEventListener('click', onImageFetchersContainerClick); } - function embed(parent, contentType, libraryOptions) { + export async function embed(parent, contentType, libraryOptions) { currentLibraryOptions = { TypeOptions: [] }; currentAvailableOptions = null; - var isNewLibrary = null === libraryOptions; + const isNewLibrary = null === libraryOptions; isNewLibrary && parent.classList.add('newlibrary'); - return new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest; - xhr.open('GET', 'components/libraryoptionseditor/libraryoptionseditor.template.html', true); - xhr.onload = function(e) { - var template = this.response; - parent.innerHTML = globalize.translateDocument(template); - populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval')); - var promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))]; - Promise.all(promises).then(function() { - return setContentType(parent, contentType).then(function() { - libraryOptions && setLibraryOptions(parent, libraryOptions); - bindEvents(parent); - resolve(); - }); - }); - }; - xhr.send(); + const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html'); + const template = await response.text(); + parent.innerHTML = globalize.translateHtml(template); + populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval')); + const promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))]; + Promise.all(promises).then(function() { + return setContentType(parent, contentType).then(function() { + libraryOptions && setLibraryOptions(parent, libraryOptions); + bindEvents(parent); + return; + }); }); } - function setAdvancedVisible(parent, visible) { - var elems = parent.querySelectorAll('.advanced'); - for (var i = 0; i < elems.length; i++) { + export function setAdvancedVisible(parent, visible) { + const elems = parent.querySelectorAll('.advanced'); + for (let i = 0; i < elems.length; i++) { visible ? elems[i].classList.remove('advancedHide') : elems[i].classList.add('advancedHide'); } } - function setContentType(parent, contentType) { + export function setContentType(parent, contentType) { if (contentType === 'homevideos' || contentType === 'photos') { parent.querySelector('.chkEnablePhotosContainer').classList.remove('hide'); } else { @@ -422,47 +426,47 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } function setSubtitleFetchersIntoOptions(parent, options) { - options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), function(elem) { + options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), elem => { return !elem.checked; - }), function(elem) { + }), elem => { return elem.getAttribute('data-pluginname'); }); - options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), function(elem) { + options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), elem => { return elem.getAttribute('data-pluginname'); }); } function setMetadataFetchersIntoOptions(parent, options) { - var sections = parent.querySelectorAll('.metadataFetcher'); - for (var i = 0; i < sections.length; i++) { - var section = sections[i]; - var type = section.getAttribute('data-type'); - var typeOptions = getTypeOptions(options, type); + const sections = parent.querySelectorAll('.metadataFetcher'); + for (let i = 0; i < sections.length; i++) { + const section = sections[i]; + const type = section.getAttribute('data-type'); + let typeOptions = getTypeOptions(options, type); if (!typeOptions) { typeOptions = { Type: type }; options.TypeOptions.push(typeOptions); } - typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), function(elem) { + typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), elem => { return elem.checked; - }), function(elem) { + }), elem => { return elem.getAttribute('data-pluginname'); }); - typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), function(elem) { + typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), elem => { return elem.getAttribute('data-pluginname'); }); } } function setImageFetchersIntoOptions(parent, options) { - var sections = parent.querySelectorAll('.imageFetcher'); - for (var i = 0; i < sections.length; i++) { - var section = sections[i]; - var type = section.getAttribute('data-type'); - var typeOptions = getTypeOptions(options, type); + const sections = parent.querySelectorAll('.imageFetcher'); + for (let i = 0; i < sections.length; i++) { + const section = sections[i]; + const type = section.getAttribute('data-type'); + let typeOptions = getTypeOptions(options, type); if (!typeOptions) { typeOptions = { Type: type @@ -470,23 +474,23 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct options.TypeOptions.push(typeOptions); } - typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), function(elem) { + typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), elem => { return elem.checked; - }), function(elem) { + }), elem => { return elem.getAttribute('data-pluginname'); }); - typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), function(elem) { + typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), elem => { return elem.getAttribute('data-pluginname'); }); } } - function setImageOptionsIntoOptions(parent, options) { - var originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || []; - for (var i = 0; i < originalTypeOptions.length; i++) { - var originalTypeOption = originalTypeOptions[i]; - var typeOptions = getTypeOptions(options, originalTypeOption.Type); + function setImageOptionsIntoOptions(options) { + const originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || []; + for (let i = 0; i < originalTypeOptions.length; i++) { + const originalTypeOption = originalTypeOptions[i]; + let typeOptions = getTypeOptions(options, originalTypeOption.Type); if (!typeOptions) { typeOptions = { @@ -498,8 +502,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct } } - function getLibraryOptions(parent) { - var options = { + export function getLibraryOptions(parent) { + const options = { EnableArchiveMediaFiles: false, EnablePhotos: parent.querySelector('.chkEnablePhotos').checked, EnableRealtimeMonitor: parent.querySelector('.chkEnableRealtimeMonitor').checked, @@ -520,39 +524,39 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct SkipSubtitlesIfAudioTrackMatches: parent.querySelector('#chkSkipIfAudioTrackPresent').checked, SaveSubtitlesWithMedia: parent.querySelector('#chkSaveSubtitlesLocally').checked, RequirePerfectSubtitleMatch: parent.querySelector('#chkRequirePerfectMatch').checked, - MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) { + MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), elem => { return elem.checked; - }), function(elem) { + }), elem => { return elem.getAttribute('data-pluginname'); }), TypeOptions: [] }; - options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), function(elem) { + options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), elem => { return elem.getAttribute('data-pluginname'); }); - options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) { + options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => { return elem.checked; - }), function(elem) { + }), elem => { return elem.getAttribute('data-lang'); }); setSubtitleFetchersIntoOptions(parent, options); setMetadataFetchersIntoOptions(parent, options); setImageFetchersIntoOptions(parent, options); - setImageOptionsIntoOptions(parent, options); + setImageOptionsIntoOptions(options); return options; } function getOrderedPlugins(plugins, configuredOrder) { plugins = plugins.slice(0); - plugins.sort(function(a, b) { + plugins.sort((a, b) => { return a = configuredOrder.indexOf(a.Name), b = configuredOrder.indexOf(b.Name), a < b ? -1 : a > b ? 1 : 0; }); return plugins; } - function setLibraryOptions(parent, options) { + export function setLibraryOptions(parent, options) { currentLibraryOptions = options; currentAvailableOptions = parent.availableOptions; parent.querySelector('#selectLanguage').value = options.PreferredMetadataLanguage || ''; @@ -573,11 +577,11 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct parent.querySelector('#chkSaveSubtitlesLocally').checked = options.SaveSubtitlesWithMedia; parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches; parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch; - Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) { - elem.checked = options.MetadataSavers ? -1 !== options.MetadataSavers.indexOf(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled'); + Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), elem => { + elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled'); }); - Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) { - elem.checked = !!options.SubtitleDownloadLanguages && -1 !== options.SubtitleDownloadLanguages.indexOf(elem.getAttribute('data-lang')); + Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => { + elem.checked = !!options.SubtitleDownloadLanguages && options.SubtitleDownloadLanguages.includes(elem.getAttribute('data-lang')); }); renderMetadataReaders(parent, getOrderedPlugins(parent.availableOptions.MetadataReaders, options.LocalMetadataReaderOrder || [])); renderMetadataFetchers(parent, parent.availableOptions, options); @@ -585,14 +589,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct renderSubtitleFetchers(parent, parent.availableOptions, options); } - var currentLibraryOptions; - var currentAvailableOptions; + let currentLibraryOptions; + let currentAvailableOptions; - return { - embed: embed, - setContentType: setContentType, - getLibraryOptions: getLibraryOptions, - setLibraryOptions: setLibraryOptions, - setAdvancedVisible: setAdvancedVisible - }; -}); +/* eslint-enable indent */ +export default { + embed: embed, + setContentType: setContentType, + getLibraryOptions: getLibraryOptions, + setLibraryOptions: setLibraryOptions, + setAdvancedVisible: setAdvancedVisible +}; diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 60340e2a0e..6b20159130 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -1,19 +1,32 @@ -define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutManager', 'globalize', 'datetime', 'cardBuilder', 'css!./listview', 'emby-ratingbutton', 'emby-playstatebutton'], function (itemHelper, mediaInfo, indicators, connectionManager, layoutManager, globalize, datetime, cardBuilder) { - 'use strict'; +/* eslint-disable indent */ + +/** + * Module for display list view. + * @module components/listview/listview + */ + +import itemHelper from 'itemHelper'; +import mediaInfo from 'mediaInfo'; +import indicators from 'indicators'; +import connectionManager from 'connectionManager'; +import layoutManager from 'layoutManager'; +import globalize from 'globalize'; +import datetime from 'datetime'; +import cardBuilder from 'cardBuilder'; +import 'css!./listview'; +import 'emby-ratingbutton'; +import 'emby-playstatebutton'; function getIndex(item, options) { - if (options.index === 'disc') { - return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber); } - var sortBy = (options.sortBy || '').toLowerCase(); - var code; - var name; + const sortBy = (options.sortBy || '').toLowerCase(); + let code; + let name; if (sortBy.indexOf('sortname') === 0) { - if (item.Type === 'Episode') { return ''; } @@ -29,11 +42,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return name.toUpperCase(); } if (sortBy.indexOf('officialrating') === 0) { - return item.OfficialRating || globalize.translate('Unrated'); } if (sortBy.indexOf('communityrating') === 0) { - if (item.CommunityRating == null) { return globalize.translate('Unrated'); } @@ -41,7 +52,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return Math.floor(item.CommunityRating); } if (sortBy.indexOf('criticrating') === 0) { - if (item.CriticRating == null) { return globalize.translate('Unrated'); } @@ -49,7 +59,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return Math.floor(item.CriticRating); } if (sortBy.indexOf('albumartist') === 0) { - // SortName if (!item.AlbumArtist) { return ''; @@ -68,11 +77,10 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } function getImageUrl(item, width) { - - var apiClient = connectionManager.getApiClient(item.ServerId); + const apiClient = connectionManager.getApiClient(item.ServerId); let itemId; - var options = { + const options = { maxWidth: width * 2, type: 'Primary' }; @@ -98,9 +106,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } function getChannelImageUrl(item, width) { - - var apiClient = connectionManager.getApiClient(item.ServerId); - var options = { + const apiClient = connectionManager.getApiClient(item.ServerId); + const options = { maxWidth: width * 2, type: 'Primary' }; @@ -115,9 +122,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } function getTextLinesHtml(textlines, isLargeStyle) { - var html = ''; + let html = ''; - var largeTitleTagName = layoutManager.tv ? 'h2' : 'div'; + const largeTitleTagName = layoutManager.tv ? 'h2' : 'div'; for (const [i, text] of textlines.entries()) { if (!text) { @@ -126,7 +133,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (i === 0) { if (isLargeStyle) { - html += '<' + largeTitleTagName + ' class="listItemBodyText">'; + html += `<${largeTitleTagName} class="listItemBodyText">`; } else { html += '
'; } @@ -135,7 +142,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } html += (textlines[i] || ' '); if (i === 0 && isLargeStyle) { - html += ''; + html += ``; } else { html += '
'; } @@ -145,14 +152,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } function getRightButtonsHtml(options) { + let html = ''; - var html = ''; + for (let i = 0, length = options.rightButtons.length; i < length; i++) { + const button = options.rightButtons[i]; - for (var i = 0, length = options.rightButtons.length; i < length; i++) { - - var button = options.rightButtons[i]; - - html += ''; + html += ``; } return html; @@ -162,37 +167,33 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return item.Id; } - function getListViewHtml(options) { + export function getListViewHtml(options) { + const items = options.items; - var items = options.items; + let groupTitle = ''; + const action = options.action || 'link'; - var groupTitle = ''; - var action = options.action || 'link'; + const isLargeStyle = options.imageSize === 'large'; + const enableOverview = options.enableOverview; - var isLargeStyle = options.imageSize === 'large'; - var enableOverview = options.enableOverview; + const clickEntireItem = layoutManager.tv ? true : false; + const outerTagName = clickEntireItem ? 'button' : 'div'; + const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true; - var clickEntireItem = layoutManager.tv ? true : false; - var outerTagName = clickEntireItem ? 'button' : 'div'; - var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true; + let outerHtml = ''; - var outerHtml = ''; + const enableContentWrapper = options.enableOverview && !layoutManager.tv; + const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId); - var enableContentWrapper = options.enableOverview && !layoutManager.tv; - var containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId); + for (let i = 0, length = items.length; i < length; i++) { + const item = items[i]; - for (var i = 0, length = items.length; i < length; i++) { - - var item = items[i]; - - var html = ''; + let html = ''; if (options.showIndex) { - - var itemGroupTitle = getIndex(item, options); + const itemGroupTitle = getIndex(item, options); if (itemGroupTitle !== groupTitle) { - if (html) { html += '

'; } @@ -211,7 +212,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } } - var cssClass = 'listItem'; + let cssClass = 'listItem'; if (options.border || (options.highlight !== false && !layoutManager.tv)) { cssClass += ' listItem-border'; @@ -225,37 +226,33 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan cssClass += ' listItem-focusscale'; } - var downloadWidth = 80; + let downloadWidth = 80; if (isLargeStyle) { cssClass += ' listItem-largeImage'; downloadWidth = 500; } - var playlistItemId = item.PlaylistItemId ? (' data-playlistitemid="' + item.PlaylistItemId + '"') : ''; + const playlistItemId = item.PlaylistItemId ? (` data-playlistitemid="${item.PlaylistItemId}"`) : ''; - var positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : ''; - var collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : ''; - var playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : ''; - var mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : ''; - var collectionTypeData = item.CollectionType ? (' data-collectiontype="' + item.CollectionType + '"') : ''; - var channelIdData = item.ChannelId ? (' data-channelid="' + item.ChannelId + '"') : ''; + const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : ''; + const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : ''; + const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : ''; + const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : ''; + const collectionTypeData = item.CollectionType ? (` data-collectiontype="${item.CollectionType}"`) : ''; + const channelIdData = item.ChannelId ? (` data-channelid="${item.ChannelId}"`) : ''; if (enableContentWrapper) { - cssClass += ' listItem-withContentWrapper'; } - html += '<' + outerTagName + ' class="' + cssClass + '"' + playlistItemId + ' data-action="' + action + '" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + '>'; + html += `<${outerTagName} class="${cssClass}"${playlistItemId} data-action="${action}" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}"${mediaTypeData}${collectionTypeData}${channelIdData}${positionTicksData}${collectionIdData}${playlistIdData}>`; if (enableContentWrapper) { - html += '
'; } if (!clickEntireItem && options.dragHandle) { - //html += ''; - // Firefox and Edge are not allowing the button to be draggable html += ''; } @@ -267,13 +264,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan imageClass += ' listItemImage-large-tv'; } - var playOnImageClick = options.imagePlayButton && !layoutManager.tv; + const playOnImageClick = options.imagePlayButton && !layoutManager.tv; if (!clickEntireItem) { imageClass += ' itemAction'; } - var imageAction = playOnImageClick ? 'link' : action; + const imageAction = playOnImageClick ? 'link' : action; if (imgUrl) { html += '
'; @@ -281,18 +278,18 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan html += '
' + cardBuilder.getDefaultText(item, options); } - var indicatorsHtml = ''; + let indicatorsHtml = ''; indicatorsHtml += indicators.getPlayedIndicatorHtml(item); if (indicatorsHtml) { - html += '
' + indicatorsHtml + '
'; + html += `
${indicatorsHtml}
`; } if (playOnImageClick) { html += ''; } - var progressHtml = indicators.getProgressBarHtml(item, { + const progressHtml = indicators.getProgressBarHtml(item, { containerClass: 'listItemProgressBar' }); @@ -303,13 +300,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } if (options.showIndexNumberLeft) { - html += '
'; html += (item.IndexNumber || ' '); html += '
'; } - var textlines = []; + const textlines = []; if (options.showProgramDateTime) { textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), { @@ -332,7 +328,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } } - var parentTitle = null; + let parentTitle = null; if (options.showParentTitle) { if (item.Type === 'Episode') { @@ -342,18 +338,16 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } } - var displayName = itemHelper.getDisplayName(item, { + let displayName = itemHelper.getDisplayName(item, { includeParentInfo: options.includeParentInfoInTitle }); if (options.showIndexNumber && item.IndexNumber != null) { - displayName = item.IndexNumber + '. ' + displayName; + displayName = `${item.IndexNumber}. ${displayName}`; } if (options.showParentTitle && options.parentTitleWithTitle) { - if (displayName) { - if (parentTitle) { parentTitle += ' - '; } @@ -371,29 +365,25 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (item.IsFolder) { if (options.artist !== false) { - if (item.AlbumArtist && item.Type === 'MusicAlbum') { textlines.push(item.AlbumArtist); } } } else { - - var showArtist = options.artist === true; - var artistItems = item.ArtistItems; + let showArtist = options.artist === true; + const artistItems = item.ArtistItems; if (!showArtist && options.artist !== false) { - if (!artistItems || !artistItems.length) { showArtist = true; - } else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) { + } else if (artistItems.length > 1 || !containerAlbumArtistIds.includes(artistItems[0].Id)) { showArtist = true; } } if (showArtist) { - if (artistItems && item.Type !== 'MusicAlbum') { - textlines.push(artistItems.map(function (a) { + textlines.push(artistItems.map(a => { return a.Name; }).join(', ')); } @@ -401,7 +391,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } if (item.Type === 'TvChannel') { - if (item.CurrentProgram) { textlines.push(itemHelper.getDisplayName(item.CurrentProgram)); } @@ -416,21 +405,22 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan cssClass += ' listItemBody-noleftpadding'; } - html += '
'; + html += `
`; html += getTextLinesHtml(textlines, isLargeStyle); if (options.mediaInfo !== false) { if (!enableSideMediaInfo) { + const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; - var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; - - html += '
' + mediaInfo.getPrimaryMediaInfoHtml(item, { + html += `
`; + html += mediaInfo.getPrimaryMediaInfoHtml(item, { episodeTitle: false, originalAirDate: false, subtitles: false - }) + '
'; + }); + html += '
'; } } @@ -444,7 +434,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan if (options.mediaInfo !== false) { if (enableSideMediaInfo) { - html += '
' + mediaInfo.getPrimaryMediaInfoHtml(item, { + html += '
'; + html += mediaInfo.getPrimaryMediaInfoHtml(item, { year: false, container: false, @@ -452,7 +443,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan criticRating: false, endsAt: false - }) + '
'; + }); + html += '
'; } } @@ -463,7 +455,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan html += '
'; if (!clickEntireItem) { - if (options.addToListButton) { html += ''; } @@ -477,9 +468,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } if (options.enableUserDataButtons !== false) { - - var userData = item.UserData || {}; - var likes = userData.Likes == null ? '' : userData.Likes; + const userData = item.UserData || {}; + const likes = userData.Likes == null ? '' : userData.Likes; if (itemHelper.canMarkPlayed(item) && options.enablePlayedButton !== false) { html += ''; @@ -506,7 +496,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan } } - html += ''; + html += ``; outerHtml += html; } @@ -514,7 +504,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return outerHtml; } - return { - getListViewHtml: getListViewHtml - }; -}); +/* eslint-enable indent */ +export default { + getListViewHtml: getListViewHtml +}; diff --git a/src/components/loading/loader.gif b/src/components/loading/loader.gif deleted file mode 100644 index 86fb6daa79..0000000000 Binary files a/src/components/loading/loader.gif and /dev/null differ diff --git a/src/components/loading/loading.js b/src/components/loading/loading.js index 9a9aa3ca7d..9f86ba452f 100644 --- a/src/components/loading/loading.js +++ b/src/components/loading/loading.js @@ -1,10 +1,6 @@ -define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], function (loadingLegacy, browser) { +define(['css!./loading'], function () { 'use strict'; - if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { - return loadingLegacy; - } - var loadingElem; var layer1; var layer2; @@ -18,7 +14,6 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio var elem = loadingElem; if (!elem) { - elem = document.createElement('div'); loadingElem = elem; @@ -60,7 +55,6 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio var elem = loadingElem; if (elem) { - elem.classList.remove('mdlSpinnerActive'); elem.classList.remove('mdl-spinner__layer-1-active'); diff --git a/src/components/loading/loadingLegacy.css b/src/components/loading/loadingLegacy.css deleted file mode 100644 index 17ea94950e..0000000000 --- a/src/components/loading/loadingLegacy.css +++ /dev/null @@ -1,10 +0,0 @@ -.loading-spinner { - margin-top: -3em; - margin-left: -3em; - width: 6em; - height: 6em; - position: fixed; - top: 50%; - left: 50%; - z-index: 9999999; -} diff --git a/src/components/loading/loadingLegacy.js b/src/components/loading/loadingLegacy.js deleted file mode 100644 index d766a4aca4..0000000000 --- a/src/components/loading/loadingLegacy.js +++ /dev/null @@ -1,28 +0,0 @@ -define(['require', 'css!./loadingLegacy'], function (require) { - 'use strict'; - - var loadingElem; - - return { - show: function () { - var elem = loadingElem; - if (!elem) { - elem = document.createElement('img'); - elem.src = require.toUrl('.').split('?')[0] + '/loader.gif'; - - loadingElem = elem; - elem.classList.add('loading-spinner'); - - document.body.appendChild(elem); - } - - elem.classList.remove('hide'); - }, - hide: function () { - var elem = loadingElem; - if (elem) { - elem.classList.add('hide'); - } - } - }; -}); diff --git a/src/components/maintabsmanager.js b/src/components/maintabsmanager.js index e1c5434363..1be1cf622f 100644 --- a/src/components/maintabsmanager.js +++ b/src/components/maintabsmanager.js @@ -1,31 +1,17 @@ -define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, browser, events) { - 'use strict'; +import dom from 'dom'; +import browser from 'browser'; +import events from 'events'; +import 'emby-tabs'; +import 'emby-button'; - var tabOwnerView; - var queryScope = document.querySelector('.skinHeader'); - var footerTabsContainer; - var headerTabsContainer; - var tabsElem; +/* eslint-disable indent */ - function enableTabsInFooter() { - return false; - } - - function getTabsContainerElem() { - } - - function ensureElements(enableInFooter) { - - if (enableInFooter) { - if (!footerTabsContainer) { - footerTabsContainer = document.createElement('div'); - footerTabsContainer.classList.add('footerTabs'); - footerTabsContainer.classList.add('sectionTabs'); - footerTabsContainer.classList.add('hide'); - //appFooter.add(footerTabsContainer); - } - } + let tabOwnerView; + const queryScope = document.querySelector('.skinHeader'); + let headerTabsContainer; + let tabsElem; + function ensureElements() { if (!headerTabsContainer) { headerTabsContainer = queryScope.querySelector('.headerTabs'); } @@ -37,14 +23,12 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, } function allowSwipe(target) { - function allowSwipeOn(elem) { - if (dom.parentWithTag(elem, 'input')) { return false; } - var classList = elem.classList; + const classList = elem.classList; if (classList) { return !classList.contains('scrollX') && !classList.contains('animatedScrollX'); } @@ -52,7 +36,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, return true; } - var parent = target; + let parent = target; while (parent != null) { if (!allowSwipeOn(parent)) { return false; @@ -64,28 +48,25 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, } function configureSwipeTabs(view, tabsElem, getTabContainersFn) { - if (!browser.touch) { return; } // implement without hammer - var pageCount = getTabContainersFn().length; - var onSwipeLeft = function (e, target) { + const onSwipeLeft = function (e, target) { if (allowSwipe(target) && view.contains(target)) { tabsElem.selectNext(); } }; - var onSwipeRight = function (e, target) { + const onSwipeRight = function (e, target) { if (allowSwipe(target) && view.contains(target)) { tabsElem.selectPrevious(); } }; - require(['touchHelper'], function (TouchHelper) { - - var touchHelper = new TouchHelper(view.parentNode.parentNode); + import('touchHelper').then(({default: TouchHelper}) => { + const touchHelper = new TouchHelper(view.parentNode.parentNode); events.on(touchHelper, 'swipeleft', onSwipeLeft); events.on(touchHelper, 'swiperight', onSwipeRight); @@ -96,29 +77,20 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, }); } - function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) { - - var enableInFooter = enableTabsInFooter(); - + export function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) { if (!view) { if (tabOwnerView) { - if (!headerTabsContainer) { headerTabsContainer = queryScope.querySelector('.headerTabs'); } - ensureElements(enableInFooter); + ensureElements(); document.body.classList.remove('withSectionTabs'); headerTabsContainer.innerHTML = ''; headerTabsContainer.classList.add('hide'); - if (footerTabsContainer) { - footerTabsContainer.innerHTML = ''; - footerTabsContainer.classList.add('hide'); - } - tabOwnerView = null; } return { @@ -127,28 +99,26 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, }; } - ensureElements(enableInFooter); + ensureElements(); - var tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer; + const tabsContainerElem = headerTabsContainer; if (!tabOwnerView) { tabsContainerElem.classList.remove('hide'); } if (tabOwnerView !== view) { + let index = 0; - var index = 0; - - var indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"'); - var tabsHtml = '
' + getTabsFn().map(function (t) { - - var tabClass = 'emby-tab-button'; + const indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"'); + const tabsHtml = '
' + getTabsFn().map(function (t) { + let tabClass = 'emby-tab-button'; if (t.enabled === false) { tabClass += ' hide'; } - var tabHtml; + let tabHtml; if (t.cssClass) { tabClass += ' ' + t.cssClass; @@ -162,7 +132,6 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, index++; return tabHtml; - }).join('') + '
'; tabsContainerElem.innerHTML = tabsHtml; @@ -176,23 +145,15 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, configureSwipeTabs(view, tabsElem, getTabContainersFn); tabsElem.addEventListener('beforetabchange', function (e) { - - var tabContainers = getTabContainersFn(); + const tabContainers = getTabContainersFn(); if (e.detail.previousIndex != null) { - - var previousPanel = tabContainers[e.detail.previousIndex]; + const previousPanel = tabContainers[e.detail.previousIndex]; if (previousPanel) { previousPanel.classList.remove('is-active'); } } - var newPanel = tabContainers[e.detail.selectedTabIndex]; - - //if (e.detail.previousIndex != null && e.detail.previousIndex != e.detail.selectedTabIndex) { - // if (newPanel.animate && (animateTabs || []).indexOf(e.detail.selectedTabIndex) != -1) { - // fadeInRight(newPanel); - // } - //} + const newPanel = tabContainers[e.detail.selectedTabIndex]; if (newPanel) { newPanel.classList.add('is-active'); @@ -210,16 +171,11 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, if (tabsElem.selectedIndex) { tabsElem.selectedIndex(selectedIndex); } else { - tabsElem.readySelectedIndex = selectedIndex; tabsElem.addEventListener('ready', onViewTabsReady); } } - //if (enableSwipe !== false) { - // libraryBrowser.configureSwipeTabs(ownerpage, tabs); - //} - return { tabsContainer: tabsContainerElem, tabs: tabsContainerElem.querySelector('[is="emby-tabs"]'), @@ -241,9 +197,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, }; } - function selectedTabIndex(index) { - - var tabsContainerElem = headerTabsContainer; + export function selectedTabIndex(index) { + const tabsContainerElem = headerTabsContainer; if (!tabsElem) { tabsElem = tabsContainerElem.querySelector('[is="emby-tabs"]'); @@ -256,13 +211,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, } } - function getTabsElement() { + export function getTabsElement() { return document.querySelector('.tabs-viewmenubar'); } - return { - setTabs: setTabs, - getTabsElement: getTabsElement, - selectedTabIndex: selectedTabIndex - }; -}); +/* eslint-enable indent */ diff --git a/src/components/mediaLibraryCreator/mediaLibraryCreator.js b/src/components/mediaLibraryCreator/mediaLibraryCreator.js index bbef6e1f07..4e0d7b026c 100644 --- a/src/components/mediaLibraryCreator/mediaLibraryCreator.js +++ b/src/components/mediaLibraryCreator/mediaLibraryCreator.js @@ -1,5 +1,24 @@ -define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-toggle', 'emby-input', 'emby-select', 'paper-icon-button-light', 'listViewStyle', 'formDialogStyle', 'emby-button', 'flexStyles'], function (loading, dialogHelper, dom, $, libraryoptionseditor, globalize) { - 'use strict'; +/* eslint-disable indent */ + +/** + * Module for media library creator. + * @module components/mediaLibraryCreator/mediaLibraryCreator + */ + +import loading from 'loading'; +import dialogHelper from 'dialogHelper'; +import dom from 'dom'; +import $ from 'jQuery'; +import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor'; +import globalize from 'globalize'; +import 'emby-toggle'; +import 'emby-input'; +import 'emby-select'; +import 'paper-icon-button-light'; +import 'listViewStyle'; +import 'formDialogStyle'; +import 'emby-button'; +import 'flexStyles'; function onAddLibrary() { if (isCreating) { @@ -7,7 +26,7 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } if (pathInfos.length == 0) { - require(['alert'], function (alert) { + import('alert').then(({default: alert}) => { alert({ text: globalize.translate('PleaseAddAtLeastOneFolder'), type: 'error' @@ -19,23 +38,23 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed isCreating = true; loading.show(); - var dlg = dom.parentWithClass(this, 'dlg-librarycreator'); - var name = $('#txtValue', dlg).val(); - var type = $('#selectCollectionType', dlg).val(); + const dlg = dom.parentWithClass(this, 'dlg-librarycreator'); + const name = $('#txtValue', dlg).val(); + let type = $('#selectCollectionType', dlg).val(); if (type == 'mixed') { type = null; } - var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); + const libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); libraryOptions.PathInfos = pathInfos; - ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(function () { + ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(() => { hasChanges = true; isCreating = false; loading.hide(); dialogHelper.close(dlg); - }, function () { - require(['toast'], function (toast) { + }, () => { + import('toast').then(({default: toast}) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); @@ -46,15 +65,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function getCollectionTypeOptionsHtml(collectionTypeOptions) { - return collectionTypeOptions.map(function (i) { - return ''; + return collectionTypeOptions.map(i => { + return ``; }).join(''); } function initEditor(page, collectionTypeOptions) { $('#selectCollectionType', page).html(getCollectionTypeOptionsHtml(collectionTypeOptions)).val('').on('change', function () { - var value = this.value; - var dlg = $(this).parents('.dialog')[0]; + const value = this.value; + const dlg = $(this).parents('.dialog')[0]; libraryoptionseditor.setContentType(dlg.querySelector('.libraryOptions'), value == 'mixed' ? '' : value); if (value) { @@ -64,12 +83,12 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } if (value != 'mixed') { - var index = this.selectedIndex; + const index = this.selectedIndex; if (index != -1) { - var name = this.options[index].innerHTML.replace('*', '').replace('&', '&'); + const name = this.options[index].innerHTML.replace('*', '').replace('&', '&'); $('#txtValue', dlg).val(name); - var folderOption = collectionTypeOptions.filter(function (i) { + const folderOption = collectionTypeOptions.filter(i => { return i.value == value; })[0]; $('.collectionTypeFieldDescription', dlg).html(folderOption.message || ''); @@ -83,15 +102,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function onToggleAdvancedChange() { - var dlg = dom.parentWithClass(this, 'dlg-librarycreator'); + const dlg = dom.parentWithClass(this, 'dlg-librarycreator'); libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked); } function onAddButtonClick() { - var page = dom.parentWithClass(this, 'dlg-librarycreator'); + const page = dom.parentWithClass(this, 'dlg-librarycreator'); - require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser(); + import('directorybrowser').then(({default: directoryBrowser}) => { + const picker = new directoryBrowser(); picker.show({ enableNetworkSharePath: true, callback: function (path, networkSharePath) { @@ -106,24 +125,24 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function getFolderHtml(pathInfo, index) { - var html = ''; + let html = ''; html += '
'; - html += '
'; - html += '
' + pathInfo.Path + '
'; + html += `
`; + html += `
${pathInfo.Path}
`; if (pathInfo.NetworkPath) { - html += '
' + pathInfo.NetworkPath + '
'; + html += `
${pathInfo.NetworkPath}
`; } html += '
'; - html += ''; + html += ``; html += '
'; return html; } function renderPaths(page) { - var foldersHtml = pathInfos.map(getFolderHtml).join(''); - var folderList = page.querySelector('.folderList'); + const foldersHtml = pathInfos.map(getFolderHtml).join(''); + const folderList = page.querySelector('.folderList'); folderList.innerHTML = foldersHtml; if (foldersHtml) { @@ -134,13 +153,13 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function addMediaLocation(page, path, networkSharePath) { - var pathLower = path.toLowerCase(); - var pathFilter = pathInfos.filter(function (p) { + const pathLower = path.toLowerCase(); + const pathFilter = pathInfos.filter(p => { return p.Path.toLowerCase() == pathLower; }); if (!pathFilter.length) { - var pathInfo = { + const pathInfo = { Path: path }; @@ -154,11 +173,11 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function onRemoveClick(e) { - var button = dom.parentWithClass(e.target, 'btnRemovePath'); - var index = parseInt(button.getAttribute('data-index')); - var location = pathInfos[index].Path; - var locationLower = location.toLowerCase(); - pathInfos = pathInfos.filter(function (p) { + const button = dom.parentWithClass(e.target, 'btnRemovePath'); + const index = parseInt(button.getAttribute('data-index')); + const location = pathInfos[index].Path; + const locationLower = location.toLowerCase(); + pathInfos = pathInfos.filter(p => { return p.Path.toLowerCase() != locationLower; }); renderPaths(dom.parentWithClass(button, 'dlg-librarycreator')); @@ -169,54 +188,49 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed } function initLibraryOptions(dlg) { - libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(function () { + libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(() => { $('#selectCollectionType', dlg).trigger('change'); onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced')); }); } - function editor() { - this.show = function (options) { - return new Promise(function (resolve, reject) { - currentOptions = options; - currentResolve = resolve; - hasChanges = false; - var xhr = new XMLHttpRequest(); - xhr.open('GET', 'components/mediaLibraryCreator/mediaLibraryCreator.template.html', true); - - xhr.onload = function (e) { - var template = this.response; - var dlg = dialogHelper.createDialog({ - size: 'small', - modal: false, - removeOnClose: true, - scrollY: false - }); - dlg.classList.add('ui-body-a'); - dlg.classList.add('background-theme-a'); - dlg.classList.add('dlg-librarycreator'); - dlg.classList.add('formDialog'); - dlg.innerHTML = globalize.translateDocument(template); - initEditor(dlg, options.collectionTypeOptions); - dlg.addEventListener('close', onDialogClosed); - dialogHelper.open(dlg); - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); - pathInfos = []; - renderPaths(dlg); - initLibraryOptions(dlg); - }; - - xhr.send(); +export class showEditor { + constructor(options) { + return new Promise((resolve) => { + currentOptions = options; + currentResolve = resolve; + hasChanges = false; + import('text!./components/mediaLibraryCreator/mediaLibraryCreator.template.html').then(({default: template}) => { + const dlg = dialogHelper.createDialog({ + size: 'small', + modal: false, + removeOnClose: true, + scrollY: false + }); + dlg.classList.add('ui-body-a'); + dlg.classList.add('background-theme-a'); + dlg.classList.add('dlg-librarycreator'); + dlg.classList.add('formDialog'); + dlg.innerHTML = globalize.translateHtml(template); + initEditor(dlg, options.collectionTypeOptions); + dlg.addEventListener('close', onDialogClosed); + dialogHelper.open(dlg); + dlg.querySelector('.btnCancel').addEventListener('click', () => { + dialogHelper.close(dlg); + }); + pathInfos = []; + renderPaths(dlg); + initLibraryOptions(dlg); }); - }; + }); } +} - var pathInfos = []; - var currentResolve; - var currentOptions; - var hasChanges = false; - var isCreating = false; - return editor; -}); + let pathInfos = []; + let currentResolve; + let currentOptions; + let hasChanges = false; + let isCreating = false; + +/* eslint-enable indent */ +export default showEditor; diff --git a/src/components/mediaLibraryEditor/mediaLibraryEditor.js b/src/components/mediaLibraryEditor/mediaLibraryEditor.js index 554cf4cc0f..1cee6984d9 100644 --- a/src/components/mediaLibraryEditor/mediaLibraryEditor.js +++ b/src/components/mediaLibraryEditor/mediaLibraryEditor.js @@ -1,5 +1,22 @@ -define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-button', 'listViewStyle', 'paper-icon-button-light', 'formDialogStyle', 'emby-toggle', 'flexStyles'], function (jQuery, loading, dialogHelper, dom, libraryoptionseditor, globalize) { - 'use strict'; +/* eslint-disable indent */ + +/** + * Module for media library editor. + * @module components/mediaLibraryEditor/mediaLibraryEditor + */ + +import jQuery from 'jQuery'; +import loading from 'loading'; +import dialogHelper from 'dialogHelper'; +import dom from 'dom'; +import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor'; +import globalize from 'globalize'; +import 'emby-button'; +import 'listViewStyle'; +import 'paper-icon-button-light'; +import 'formDialogStyle'; +import 'emby-toggle'; +import 'flexStyles'; function onEditLibrary() { if (isCreating) { @@ -8,15 +25,15 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed isCreating = true; loading.show(); - var dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); - var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); + const dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); + let libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); libraryOptions = Object.assign(currentOptions.library.LibraryOptions || {}, libraryOptions); - ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(function () { + ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(() => { hasChanges = true; isCreating = false; loading.hide(); dialogHelper.close(dlg); - }, function () { + }, () => { isCreating = false; loading.hide(); }); @@ -24,50 +41,50 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function addMediaLocation(page, path, networkSharePath) { - var virtualFolder = currentOptions.library; - var refreshAfterChange = currentOptions.refresh; - ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(function () { + const virtualFolder = currentOptions.library; + const refreshAfterChange = currentOptions.refresh; + ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(() => { hasChanges = true; refreshLibraryFromServer(page); - }, function () { - require(['toast'], function (toast) { + }, () => { + import('toast').then(({default: toast}) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); }); } function updateMediaLocation(page, path, networkSharePath) { - var virtualFolder = currentOptions.library; + const virtualFolder = currentOptions.library; ApiClient.updateMediaPath(virtualFolder.Name, { Path: path, NetworkPath: networkSharePath - }).then(function () { + }).then(() => { hasChanges = true; refreshLibraryFromServer(page); - }, function () { - require(['toast'], function (toast) { + }, () => { + import('toast').then(({default: toast}) => { toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); }); }); } function onRemoveClick(btnRemovePath, location) { - var button = btnRemovePath; - var virtualFolder = currentOptions.library; + const button = btnRemovePath; + const virtualFolder = currentOptions.library; - require(['confirm'], function (confirm) { + import('confirm').then(({default: confirm}) => { confirm({ title: globalize.translate('HeaderRemoveMediaLocation'), text: globalize.translate('MessageConfirmRemoveMediaLocation'), confirmText: globalize.translate('ButtonDelete'), primary: 'delete' - }).then(function () { - var refreshAfterChange = currentOptions.refresh; - ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(function () { + }).then(() => { + const refreshAfterChange = currentOptions.refresh; + ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(() => { hasChanges = true; refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor')); - }, function () { - require(['toast'], function (toast) { + }, () => { + import('toast').then(({default: toast}) => { toast(globalize.translate('DefaultErrorMessage')); }); }); @@ -76,14 +93,14 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function onListItemClick(e) { - var listItem = dom.parentWithClass(e.target, 'listItem'); + const listItem = dom.parentWithClass(e.target, 'listItem'); if (listItem) { - var index = parseInt(listItem.getAttribute('data-index')); - var pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || []; - var pathInfo = null == index ? {} : pathInfos[index] || {}; - var originalPath = pathInfo.Path || (null == index ? null : currentOptions.library.Locations[index]); - var btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath'); + const index = parseInt(listItem.getAttribute('data-index')); + const pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || []; + const pathInfo = null == index ? {} : pathInfos[index] || {}; + const originalPath = pathInfo.Path || (null == index ? null : currentOptions.library.Locations[index]); + const btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath'); if (btnRemovePath) { onRemoveClick(btnRemovePath, originalPath); @@ -95,26 +112,26 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function getFolderHtml(pathInfo, index) { - var html = ''; - html += '
'; - html += '
'; + let html = ''; + html += `
`; + html += `
`; html += '

'; html += pathInfo.Path; html += '

'; if (pathInfo.NetworkPath) { - html += '
' + pathInfo.NetworkPath + '
'; + html += `
${pathInfo.NetworkPath}
`; } html += '
'; - html += ''; + html += ``; html += '
'; return html; } function refreshLibraryFromServer(page) { - ApiClient.getVirtualFolders().then(function (result) { - var library = result.filter(function (f) { + ApiClient.getVirtualFolders().then(result => { + const library = result.filter(f => { return f.Name === currentOptions.library.Name; })[0]; @@ -126,10 +143,10 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function renderLibrary(page, options) { - var pathInfos = (options.library.LibraryOptions || {}).PathInfos || []; + let pathInfos = (options.library.LibraryOptions || {}).PathInfos || []; if (!pathInfos.length) { - pathInfos = options.library.Locations.map(function (p) { + pathInfos = options.library.Locations.map(p => { return { Path: p }; @@ -150,8 +167,8 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function showDirectoryBrowser(context, originalPath, networkPath) { - require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser(); + import('directorybrowser').then(({default: directoryBrowser}) => { + const picker = new directoryBrowser(); picker.show({ enableNetworkSharePath: true, pathReadOnly: null != originalPath, @@ -173,7 +190,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed } function onToggleAdvancedChange() { - var dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); + const dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked); } @@ -183,7 +200,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed dlg.querySelector('.folderList').addEventListener('click', onListItemClick); dlg.querySelector('.chkAdvanced').addEventListener('change', onToggleAdvancedChange); dlg.querySelector('.btnSubmit').addEventListener('click', onEditLibrary); - libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(function () { + libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(() => { onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced')); }); } @@ -192,46 +209,41 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed currentDeferred.resolveWith(null, [hasChanges]); } - function editor() { - this.show = function (options) { - var deferred = jQuery.Deferred(); - currentOptions = options; - currentDeferred = deferred; - hasChanges = false; - var xhr = new XMLHttpRequest(); - xhr.open('GET', 'components/mediaLibraryEditor/mediaLibraryEditor.template.html', true); - - xhr.onload = function (e) { - var template = this.response; - var dlg = dialogHelper.createDialog({ - size: 'small', - modal: false, - removeOnClose: true, - scrollY: false - }); - dlg.classList.add('dlg-libraryeditor'); - dlg.classList.add('ui-body-a'); - dlg.classList.add('background-theme-a'); - dlg.classList.add('formDialog'); - dlg.innerHTML = globalize.translateDocument(template); - dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name; - initEditor(dlg, options); - dlg.addEventListener('close', onDialogClosed); - dialogHelper.open(dlg); - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); - refreshLibraryFromServer(dlg); - }; - - xhr.send(); - return deferred.promise(); - }; +export class showEditor { + constructor(options) { + const deferred = jQuery.Deferred(); + currentOptions = options; + currentDeferred = deferred; + hasChanges = false; + import('text!./components/mediaLibraryEditor/mediaLibraryEditor.template.html').then(({default: template}) => { + const dlg = dialogHelper.createDialog({ + size: 'small', + modal: false, + removeOnClose: true, + scrollY: false + }); + dlg.classList.add('dlg-libraryeditor'); + dlg.classList.add('ui-body-a'); + dlg.classList.add('background-theme-a'); + dlg.classList.add('formDialog'); + dlg.innerHTML = globalize.translateHtml(template); + dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name; + initEditor(dlg, options); + dlg.addEventListener('close', onDialogClosed); + dialogHelper.open(dlg); + dlg.querySelector('.btnCancel').addEventListener('click', () => { + dialogHelper.close(dlg); + }); + refreshLibraryFromServer(dlg); + }); + return deferred.promise(); } +} - var currentDeferred; - var currentOptions; - var hasChanges = false; - var isCreating = false; - return editor; -}); + let currentDeferred; + let currentOptions; + let hasChanges = false; + let isCreating = false; + +/* eslint-enable indent */ +export default showEditor; diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 7de11c42f7..53982040b8 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -1,24 +1,29 @@ -define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'material-icons', 'css!./mediainfo.css', 'programStyles', 'emby-button'], function (datetime, globalize, appRouter, itemHelper, indicators) { - 'use strict'; +import datetime from 'datetime'; +import globalize from 'globalize'; +import appRouter from 'appRouter'; +import itemHelper from 'itemHelper'; +import indicators from 'indicators'; +import 'material-icons'; +import 'css!./mediainfo.css'; +import 'programStyles'; +import 'emby-button'; + +/* eslint-disable indent */ function getTimerIndicator(item) { - - var status; + let status; if (item.Type === 'SeriesTimer') { return ''; } else if (item.TimerId || item.SeriesTimerId) { - status = item.Status || 'Cancelled'; } else if (item.Type === 'Timer') { - status = item.Status; } else { return ''; } if (item.SeriesTimerId) { - if (status !== 'Cancelled') { return ''; } @@ -30,16 +35,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } function getProgramInfoHtml(item, options) { - var html = ''; + let html = ''; - var miscInfo = []; - var text; - var date; + const miscInfo = []; + let text; + let date; if (item.StartDate && options.programTime !== false) { - try { - text = ''; date = datetime.parseISO8601Date(item.StartDate); @@ -48,35 +51,34 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater text += datetime.toLocaleDateString(date, { weekday: 'short', month: 'short', day: 'numeric' }); } - text += ' ' + datetime.getDisplayTime(date); + text += ` ${datetime.getDisplayTime(date)}`; if (item.EndDate) { date = datetime.parseISO8601Date(item.EndDate); - text += ' - ' + datetime.getDisplayTime(date); + text += ` - ${datetime.getDisplayTime(date)}`; } miscInfo.push(text); } catch (e) { - console.error('error parsing date: ' + item.StartDate); + console.error('error parsing date:', item.StartDate); } } if (item.ChannelNumber) { - miscInfo.push('CH ' + item.ChannelNumber); + miscInfo.push(`CH ${item.ChannelNumber}`); } if (item.ChannelName) { - if (options.interactive && item.ChannelId) { miscInfo.push({ - html: '' + item.ChannelName + '' + })}">${item.ChannelName}` }); } else { miscInfo.push(item.ChannelName); @@ -84,7 +86,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (options.timerIndicator !== false) { - var timerHtml = getTimerIndicator(item); + const timerHtml = getTimerIndicator(item); if (timerHtml) { miscInfo.push({ html: timerHtml @@ -92,31 +94,29 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } } - html += miscInfo.map(function (m) { + html += miscInfo.map(m => { return getMediaInfoItem(m); }).join(''); return html; } - function getMediaInfoHtml(item, options) { - var html = ''; + export function getMediaInfoHtml(item, options) { + let html = ''; - var miscInfo = []; + const miscInfo = []; options = options || {}; - var text; - var date; - var minutes; - var count; + let text; + let date; + let minutes; + let count; - var showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre'; + const showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre'; if (showFolderRuntime) { - count = item.SongCount || item.ChildCount; if (count) { - miscInfo.push(globalize.translate('TrackCount', count)); } @@ -124,33 +124,28 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks)); } } else if (item.Type === 'PhotoAlbum' || item.Type === 'BoxSet') { - count = item.ChildCount; if (count) { - miscInfo.push(globalize.translate('ItemCount', count)); } } if ((item.Type === 'Episode' || item.MediaType === 'Photo') && options.originalAirDate !== false) { - if (item.PremiereDate) { - try { date = datetime.parseISO8601Date(item.PremiereDate); text = datetime.toLocaleDateString(date); miscInfo.push(text); } catch (e) { - console.error('error parsing date: ' + item.PremiereDate); + console.error('error parsing date:', item.PremiereDate); } } } if (item.Type === 'SeriesTimer') { if (item.RecordAnyTime) { - miscInfo.push(globalize.translate('Anytime')); } else { miscInfo.push(datetime.getDisplayTime(item.StartDate)); @@ -164,7 +159,6 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (item.StartDate && item.Type !== 'Program' && item.Type !== 'SeriesTimer') { - try { date = datetime.parseISO8601Date(item.StartDate); @@ -176,31 +170,25 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater miscInfo.push(text); } } catch (e) { - console.error('error parsing date: ' + item.StartDate); + console.error('error parsing date:', item.StartDate); } } if (options.year !== false && item.ProductionYear && item.Type === 'Series') { - if (item.Status === 'Continuing') { miscInfo.push(globalize.translate('SeriesYearToPresent', item.ProductionYear)); - } else if (item.ProductionYear) { - text = item.ProductionYear; if (item.EndDate) { - try { - - var endYear = datetime.parseISO8601Date(item.EndDate).getFullYear(); + const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear(); if (endYear !== item.ProductionYear) { - text += '-' + datetime.parseISO8601Date(item.EndDate).getFullYear(); + text += `-${datetime.parseISO8601Date(item.EndDate).getFullYear()}`; } - } catch (e) { - console.error('error parsing date: ' + item.EndDate); + console.error('error parsing date:', item.EndDate); } } @@ -209,29 +197,27 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (item.Type === 'Program') { - if (options.programIndicator !== false) { if (item.IsLive) { miscInfo.push({ - html: '
' + globalize.translate('Live') + '
' + html: `
${globalize.translate('Live')}
` }); } else if (item.IsPremiere) { miscInfo.push({ - html: '
' + globalize.translate('Premiere') + '
' + html: `
${globalize.translate('Premiere')}
` }); } else if (item.IsSeries && !item.IsRepeat) { miscInfo.push({ - html: '
' + globalize.translate('AttributeNew') + '
' + html: `
${globalize.translate('AttributeNew')}
` }); } else if (item.IsSeries && item.IsRepeat) { miscInfo.push({ - html: '
' + globalize.translate('Repeat') + '
' + html: `
${globalize.translate('Repeat')}
` }); } } if ((item.IsSeries || item.EpisodeTitle) && options.episodeTitle !== false) { - text = itemHelper.getDisplayName(item, { includeIndexNumber: options.episodeTitleIndexNumber }); @@ -242,13 +228,12 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } else if (item.IsMovie && item.ProductionYear && options.originalAirDate !== false) { miscInfo.push(item.ProductionYear); } else if (item.PremiereDate && options.originalAirDate !== false) { - try { date = datetime.parseISO8601Date(item.PremiereDate); text = globalize.translate('OriginalAirDateValue', datetime.toLocaleDateString(date)); miscInfo.push(text); } catch (e) { - console.error('error parsing date: ' + item.PremiereDate); + console.error('error parsing date:', item.PremiereDate); } } else if (item.ProductionYear) { miscInfo.push(item.ProductionYear); @@ -257,34 +242,28 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater if (options.year !== false) { if (item.Type !== 'Series' && item.Type !== 'Episode' && item.Type !== 'Person' && item.MediaType !== 'Photo' && item.Type !== 'Program' && item.Type !== 'Season') { - if (item.ProductionYear) { - miscInfo.push(item.ProductionYear); } else if (item.PremiereDate) { - try { text = datetime.parseISO8601Date(item.PremiereDate).getFullYear(); miscInfo.push(text); } catch (e) { - console.error('error parsing date: ' + item.PremiereDate); + console.error('error parsing date:', item.PremiereDate); } } } } if (item.RunTimeTicks && item.Type !== 'Series' && item.Type !== 'Program' && item.Type !== 'Book' && !showFolderRuntime && options.runtime !== false) { - if (item.Type === 'Audio') { - miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks)); - } else { minutes = item.RunTimeTicks / 600000000; minutes = minutes || 1; - miscInfo.push(Math.round(minutes) + ' mins'); + miscInfo.push(`${Math.round(minutes)} mins`); } } @@ -300,14 +279,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (item.MediaType === 'Photo' && item.Width && item.Height) { - miscInfo.push(item.Width + 'x' + item.Height); + miscInfo.push(`${item.Width}x${item.Height}`); } if (options.container !== false && item.Type === 'Audio' && item.Container) { miscInfo.push(item.Container); } - html += miscInfo.map(function (m) { + html += miscInfo.map(m => { return getMediaInfoItem(m); }).join(''); @@ -318,17 +297,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (item.CriticRating && options.criticRating !== false) { - if (item.CriticRating >= 60) { - html += '
' + item.CriticRating + '
'; + html += `
${item.CriticRating}
`; } else { - html += '
' + item.CriticRating + '
'; + html += `
${item.CriticRating}
`; } } if (options.endsAt !== false) { - - var endsAt = getEndsAt(item); + const endsAt = getEndsAt(item); if (endsAt) { html += getMediaInfoItem(endsAt, 'endsAt'); } @@ -339,15 +316,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return html; } - function getEndsAt(item) { - + export function getEndsAt(item) { if (item.MediaType === 'Video' && item.RunTimeTicks) { - if (!item.StartDate) { - var endDate = new Date().getTime() + (item.RunTimeTicks / 10000); + let endDate = new Date().getTime() + (item.RunTimeTicks / 10000); endDate = new Date(endDate); - var displayTime = datetime.getDisplayTime(endDate); + const displayTime = datetime.getDisplayTime(endDate); return globalize.translate('EndsAtValue', displayTime); } } @@ -355,12 +330,11 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return null; } - function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) { - - var endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000); + export function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) { + let endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000); endDate = new Date(endDate); - var displayTime = datetime.getDisplayTime(endDate); + const displayTime = datetime.getDisplayTime(endDate); if (includeText === false) { return displayTime; @@ -369,23 +343,21 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } function getMediaInfoItem(m, cssClass) { - - cssClass = cssClass ? (cssClass + ' mediaInfoItem') : 'mediaInfoItem'; - var mediaInfoText = m; + cssClass = cssClass ? (`${cssClass} mediaInfoItem`) : 'mediaInfoItem'; + let mediaInfoText = m; if (typeof (m) !== 'string' && typeof (m) !== 'number') { - if (m.html) { return m.html; } mediaInfoText = m.text; - cssClass += ' ' + m.cssClass; + cssClass += ` ${m.cssClass}`; } - return '
' + mediaInfoText + '
'; + return `
${mediaInfoText}
`; } function getStarIconsHtml(item) { - var html = ''; + let html = ''; if (item.CommunityRating) { html += '
'; @@ -399,53 +371,47 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } function dynamicEndTime(elem, item) { - - var interval = setInterval(function () { - + const interval = setInterval(() => { if (!document.body.contains(elem)) { - clearInterval(interval); return; } elem.innerHTML = getEndsAt(item); - }, 60000); } - function fillPrimaryMediaInfo(elem, item, options) { - var html = getPrimaryMediaInfoHtml(item, options); + export function fillPrimaryMediaInfo(elem, item, options) { + const html = getPrimaryMediaInfoHtml(item, options); elem.innerHTML = html; afterFill(elem, item, options); } - function fillSecondaryMediaInfo(elem, item, options) { - var html = getSecondaryMediaInfoHtml(item, options); + export function fillSecondaryMediaInfo(elem, item, options) { + const html = getSecondaryMediaInfoHtml(item, options); elem.innerHTML = html; afterFill(elem, item, options); } function afterFill(elem, item, options) { - if (options.endsAt !== false) { - var endsAtElem = elem.querySelector('.endsAt'); + const endsAtElem = elem.querySelector('.endsAt'); if (endsAtElem) { dynamicEndTime(endsAtElem, item); } } - var lnkChannel = elem.querySelector('.lnkChannel'); + const lnkChannel = elem.querySelector('.lnkChannel'); if (lnkChannel) { lnkChannel.addEventListener('click', onChannelLinkClick); } } function onChannelLinkClick(e) { - - var channelId = this.getAttribute('data-id'); - var serverId = this.getAttribute('data-serverid'); + const channelId = this.getAttribute('data-id'); + const serverId = this.getAttribute('data-serverid'); appRouter.showItem(channelId, serverId); @@ -453,8 +419,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return false; } - function getPrimaryMediaInfoHtml(item, options) { - + export function getPrimaryMediaInfoHtml(item, options) { options = options || {}; if (options.interactive == null) { options.interactive = false; @@ -463,8 +428,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return getMediaInfoHtml(item, options); } - function getSecondaryMediaInfoHtml(item, options) { - + export function getSecondaryMediaInfoHtml(item, options) { options = options || {}; if (options.interactive == null) { options.interactive = false; @@ -476,13 +440,11 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return ''; } - function getResolutionText(i) { - - var width = i.Width; - var height = i.Height; + export function getResolutionText(i) { + const width = i.Width; + const height = i.Height; if (width && height) { - if (width >= 3800 || height >= 2000) { return '4K'; } @@ -505,45 +467,41 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater return '720p'; } if (width >= 700 || height >= 400) { - if (i.IsInterlaced) { return '480i'; } return '480p'; } - } return null; } function getAudioStreamForDisplay(item) { - if (!item.MediaSources) { return null; } - var mediaSource = item.MediaSources[0]; + const mediaSource = item.MediaSources[0]; if (!mediaSource) { return null; } - return (mediaSource.MediaStreams || []).filter(function (i) { + return (mediaSource.MediaStreams || []).filter(i => { return i.Type === 'Audio' && (i.Index === mediaSource.DefaultAudioStreamIndex || mediaSource.DefaultAudioStreamIndex == null); })[0]; } - function getMediaInfoStats(item, options) { - + export function getMediaInfoStats(item, options) { options = options || {}; - var list = []; + const list = []; - var mediaSource = (item.MediaSources || [])[0] || {}; + const mediaSource = (item.MediaSources || [])[0] || {}; - var videoStream = (mediaSource.MediaStreams || []).filter(function (i) { + const videoStream = (mediaSource.MediaStreams || []).filter(i => { return i.Type === 'Video'; })[0] || {}; - var audioStream = getAudioStreamForDisplay(item) || {}; + const audioStream = getAudioStreamForDisplay(item) || {}; if (item.VideoType === 'Dvd') { list.push({ @@ -559,11 +517,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater }); } - //if (mediaSource.Container) { - // html += '
' + mediaSource.Container + '
'; - //} - - var resolutionText = getResolutionText(videoStream); + const resolutionText = getResolutionText(videoStream); if (resolutionText) { list.push({ type: 'mediainfo', @@ -578,23 +532,16 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater }); } - var channels = audioStream.Channels; - var channelText; + const channels = audioStream.Channels; + let channelText; if (channels === 8) { - channelText = '7.1'; - } else if (channels === 7) { - channelText = '6.1'; - } else if (channels === 6) { - channelText = '5.1'; - } else if (channels === 2) { - channelText = '2.0'; } @@ -605,7 +552,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater }); } - var audioCodec = (audioStream.Codec || '').toLowerCase(); + const audioCodec = (audioStream.Codec || '').toLowerCase(); if ((audioCodec === 'dca' || audioCodec === 'dts') && audioStream.Profile) { list.push({ @@ -620,28 +567,27 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater } if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) { - - var dateCreated = datetime.parseISO8601Date(item.DateCreated); + const dateCreated = datetime.parseISO8601Date(item.DateCreated); list.push({ type: 'added', - text: globalize.translate('AddedOnValue', datetime.toLocaleDateString(dateCreated) + ' ' + datetime.getDisplayTime(dateCreated)) + text: globalize.translate('AddedOnValue', `${datetime.toLocaleDateString(dateCreated)} ${datetime.getDisplayTime(dateCreated)}`) }); } return list; } - return { - getMediaInfoHtml: getPrimaryMediaInfoHtml, - fill: fillPrimaryMediaInfo, - getEndsAt: getEndsAt, - getEndsAtFromPosition: getEndsAtFromPosition, - getPrimaryMediaInfoHtml: getPrimaryMediaInfoHtml, - getSecondaryMediaInfoHtml: getSecondaryMediaInfoHtml, - fillPrimaryMediaInfo: fillPrimaryMediaInfo, - fillSecondaryMediaInfo: fillSecondaryMediaInfo, - getMediaInfoStats: getMediaInfoStats, - getResolutionText: getResolutionText - }; -}); +/* eslint-enable indent */ + +export default { + getMediaInfoHtml: getPrimaryMediaInfoHtml, + getEndsAt: getEndsAt, + getEndsAtFromPosition: getEndsAtFromPosition, + getPrimaryMediaInfoHtml: getPrimaryMediaInfoHtml, + getSecondaryMediaInfoHtml: getSecondaryMediaInfoHtml, + fillPrimaryMediaInfo: fillPrimaryMediaInfo, + fillSecondaryMediaInfo: fillSecondaryMediaInfo, + getMediaInfoStats: getMediaInfoStats, + getResolutionText: getResolutionText +}; diff --git a/src/components/metadataEditor/metadataEditor.js b/src/components/metadataEditor/metadataEditor.js index 61a4ba7f24..be44e86b44 100644 --- a/src/components/metadataEditor/metadataEditor.js +++ b/src/components/metadataEditor/metadataEditor.js @@ -1,25 +1,42 @@ -define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loading', 'focusManager', 'connectionManager', 'globalize', 'require', 'shell', 'emby-checkbox', 'emby-input', 'emby-select', 'listViewStyle', 'emby-textarea', 'emby-button', 'paper-icon-button-light', 'css!./../formdialog', 'clearButtonStyle', 'flexStyles'], function (itemHelper, dom, layoutManager, dialogHelper, datetime, loading, focusManager, connectionManager, globalize, require, shell) { - 'use strict'; +import dom from 'dom'; +import layoutManager from 'layoutManager'; +import dialogHelper from 'dialogHelper'; +import datetime from 'datetime'; +import loading from 'loading'; +import focusManager from 'focusManager'; +import connectionManager from 'connectionManager'; +import globalize from 'globalize'; +import require from 'require'; +import shell from 'shell'; +import 'emby-checkbox'; +import 'emby-input'; +import 'emby-select'; +import 'listViewStyle'; +import 'emby-textarea'; +import 'emby-button'; +import 'paper-icon-button-light'; +import 'css!./../formdialog'; +import 'clearButtonStyle'; +import 'flexStyles'; - var currentContext; - var metadataEditorInfo; - var currentItem; +/* eslint-disable indent */ + + let currentContext; + let metadataEditorInfo; + let currentItem; function isDialog() { return currentContext.classList.contains('dialog'); } function closeDialog(isSubmitted) { - if (isDialog()) { dialogHelper.close(currentContext); } } function submitUpdatedItem(form, item) { - function afterContentTypeUpdated() { - require(['toast'], function (toast) { toast(globalize.translate('MessageItemSaved')); }); @@ -28,14 +45,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi closeDialog(true); } - var apiClient = getApiClient(); + const apiClient = getApiClient(); apiClient.updateItem(item).then(function () { - - var newContentType = form.querySelector('#selectContentType').value || ''; + const newContentType = form.querySelector('#selectContentType').value || ''; if ((metadataEditorInfo.ContentType || '') !== newContentType) { - apiClient.ajax({ url: apiClient.getUrl('Items/' + item.Id + '/ContentType', { @@ -47,29 +62,23 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi }).then(function () { afterContentTypeUpdated(); }); - } else { afterContentTypeUpdated(); } - }); } function getSelectedAirDays(form) { - var checkedItems = form.querySelectorAll('.chkAirDay:checked') || []; + const checkedItems = form.querySelectorAll('.chkAirDay:checked') || []; return Array.prototype.map.call(checkedItems, function (c) { return c.getAttribute('data-day'); }); } function getAlbumArtists(form) { - return form.querySelector('#txtAlbumArtist').value.trim().split(';').filter(function (s) { - return s.length > 0; - }).map(function (a) { - return { Name: a }; @@ -77,13 +86,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getArtists(form) { - return form.querySelector('#txtArtist').value.trim().split(';').filter(function (s) { - return s.length > 0; - }).map(function (a) { - return { Name: a }; @@ -91,23 +96,20 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getDateValue(form, element, property) { - - var val = form.querySelector(element).value; + let val = form.querySelector(element).value; if (!val) { return null; } if (currentItem[property]) { + const date = datetime.parseISO8601Date(currentItem[property], true); - var date = datetime.parseISO8601Date(currentItem[property], true); - - var parts = date.toISOString().split('T'); + const parts = date.toISOString().split('T'); // If the date is the same, preserve the time if (parts[0].indexOf(val) === 0) { - - var iso = parts[1]; + const iso = parts[1]; val += 'T' + iso; } @@ -117,12 +119,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function onSubmit(e) { - loading.show(); - var form = this; + const form = this; - var item = { + const item = { Id: currentItem.Id, Name: form.querySelector('#txtName').value, OriginalTitle: form.querySelector('#txtOriginalName').value, @@ -168,9 +169,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi item.ProviderIds = Object.assign({}, currentItem.ProviderIds); - var idElements = form.querySelectorAll('.txtExternalId'); + const idElements = form.querySelectorAll('.txtExternalId'); Array.prototype.map.call(idElements, function (idElem) { - var providerKey = idElem.getAttribute('data-providerkey'); + const providerKey = idElem.getAttribute('data-providerkey'); item.ProviderIds[providerKey] = idElem.value; }); @@ -178,20 +179,18 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi item.PreferredMetadataCountryCode = form.querySelector('#selectCountry').value; if (currentItem.Type === 'Person') { - - var placeOfBirth = form.querySelector('#txtPlaceOfBirth').value; + const placeOfBirth = form.querySelector('#txtPlaceOfBirth').value; item.ProductionLocations = placeOfBirth ? [placeOfBirth] : []; } if (currentItem.Type === 'Series') { - // 600000000 - var seriesRuntime = form.querySelector('#txtSeriesRuntime').value; + const seriesRuntime = form.querySelector('#txtSeriesRuntime').value; item.RunTimeTicks = seriesRuntime ? (seriesRuntime * 600000000) : null; } - var tagline = form.querySelector('#txtTagline').value; + const tagline = form.querySelector('#txtTagline').value; item.Taglines = tagline ? [tagline] : []; submitUpdatedItem(form, item); @@ -210,13 +209,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function addElementToList(source, sortCallback) { - require(['prompt'], function (prompt) { - + import('prompt').then(({default: prompt}) => { prompt({ label: 'Value:' }).then(function (text) { - var list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList'); - var items = getListValues(list); + const list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList'); + const items = getListValues(list); items.push(text); populateListView(list, items, sortCallback); }); @@ -224,17 +222,14 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function removeElementFromList(source) { - var el = dom.parentWithClass(source, 'listItem'); + const el = dom.parentWithClass(source, 'listItem'); el.parentNode.removeChild(el); } function editPerson(context, person, index) { - require(['personEditor'], function (personEditor) { - personEditor.show(person).then(function (updatedPerson) { - - var isNew = index === -1; + const isNew = index === -1; if (isNew) { currentItem.People.push(updatedPerson); @@ -245,15 +240,51 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi }); } - function onEditorClick(e) { + function afterDeleted(context, item) { + var parentId = item.ParentId || item.SeasonId || item.SeriesId; - var btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList'); + if (parentId) { + reload(context, parentId, item.ServerId); + } else { + require(['appRouter'], function (appRouter) { + appRouter.goHome(); + }); + } + } + + function showMoreMenu(context, button, user) { + require(['itemContextMenu'], function (itemContextMenu) { + var item = currentItem; + + itemContextMenu.show({ + item: item, + positionTo: button, + edit: false, + editImages: true, + editSubtitles: true, + sync: false, + share: false, + play: false, + queue: false, + user: user + }).then(function (result) { + if (result.deleted) { + afterDeleted(context, item); + } else if (result.updated) { + reload(context, item.Id, item.ServerId); + } + }); + }); + } + + function onEditorClick(e) { + const btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList'); if (btnRemoveFromEditorList) { removeElementFromList(btnRemoveFromEditorList); return; } - var btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem'); + const btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem'); if (btnAddTextItem) { addElementToList(btnAddTextItem); } @@ -264,19 +295,18 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function bindAll(elems, eventName, fn) { - for (var i = 0, length = elems.length; i < length; i++) { + for (let i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener(eventName, fn); } } function init(context, apiClient) { - context.querySelector('.externalIds').addEventListener('click', function (e) { - var btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId'); + const btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId'); if (btnOpenExternalId) { - var field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid')); + const field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid')); - var formatString = field.getAttribute('data-formatstring'); + const formatString = field.getAttribute('data-formatstring'); if (field.value) { shell.openUrl(formatString.replace('{0}', field.value)); @@ -294,13 +324,17 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi closeDialog(false); }); - context.querySelector('.btnHeaderSave').addEventListener('click', function (e) { + context.querySelector('.btnMore').addEventListener('click', function (e) { + getApiClient().getCurrentUser().then(function (user) { + showMoreMenu(context, e.target, user); + }); + }); + context.querySelector('.btnHeaderSave').addEventListener('click', function (e) { context.querySelector('.btnSave').click(); }); context.querySelector('#chkLockData').addEventListener('click', function (e) { - if (!e.target.checked) { showElement('.providerSettingsContainer'); } else { @@ -311,26 +345,24 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi context.removeEventListener('click', onEditorClick); context.addEventListener('click', onEditorClick); - var form = context.querySelector('form'); + const form = context.querySelector('form'); form.removeEventListener('submit', onSubmit); form.addEventListener('submit', onSubmit); context.querySelector('#btnAddPerson').addEventListener('click', function (event, data) { - editPerson(context, {}, -1); }); context.querySelector('#peopleList').addEventListener('click', function (e) { - - var index; - var btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson'); + let index; + const btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson'); if (btnDeletePerson) { index = parseInt(btnDeletePerson.getAttribute('data-index')); currentItem.People.splice(index, 1); populatePeople(context, currentItem.People); } - var btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson'); + const btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson'); if (btnEditPerson) { index = parseInt(btnEditPerson.getAttribute('data-index')); editPerson(context, currentItem.People[index], index); @@ -339,8 +371,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getItem(itemId, serverId) { - - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); if (itemId) { return apiClient.getItem(apiClient.getCurrentUserId(), itemId); @@ -350,8 +381,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getEditorConfig(itemId, serverId) { - - var apiClient = connectionManager.getApiClient(serverId); + const apiClient = connectionManager.getApiClient(serverId); if (itemId) { return apiClient.getJSON(apiClient.getUrl('Items/' + itemId + '/MetadataEditor')); @@ -361,14 +391,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populateCountries(select, allCountries) { - - var html = ''; + let html = ''; html += ""; - for (var i = 0, length = allCountries.length; i < length; i++) { - - var culture = allCountries[i]; + for (let i = 0, length = allCountries.length; i < length; i++) { + const culture = allCountries[i]; html += "'; } @@ -377,14 +405,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populateLanguages(select, languages) { - - var html = ''; + let html = ''; html += ""; - for (var i = 0, length = languages.length; i < length; i++) { - - var culture = languages[i]; + for (let i = 0, length = languages.length; i < length; i++) { + const culture = languages[i]; html += "'; } @@ -393,48 +419,43 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function renderContentTypeOptions(context, metadataInfo) { - if (!metadataInfo.ContentTypeOptions.length) { hideElement('#fldContentType', context); } else { showElement('#fldContentType', context); } - var html = metadataInfo.ContentTypeOptions.map(function (i) { - + const html = metadataInfo.ContentTypeOptions.map(function (i) { return ''; - }).join(''); - var selectEl = context.querySelector('#selectContentType'); + const selectEl = context.querySelector('#selectContentType'); selectEl.innerHTML = html; selectEl.value = metadataInfo.ContentType || ''; } function loadExternalIds(context, item, externalIds) { + let html = ''; - var html = ''; + const providerIds = item.ProviderIds || {}; - var providerIds = item.ProviderIds || {}; + for (let i = 0, length = externalIds.length; i < length; i++) { + const idInfo = externalIds[i]; - for (var i = 0, length = externalIds.length; i < length; i++) { + const id = 'txt1' + idInfo.Key; + const formatString = idInfo.UrlFormatString || ''; - var idInfo = externalIds[i]; - - var id = 'txt1' + idInfo.Key; - var formatString = idInfo.UrlFormatString || ''; - - var fullName = idInfo.Name; + let fullName = idInfo.Name; if (idInfo.Type) { fullName = idInfo.Name + ' ' + globalize.translate(idInfo.Type); } - var labelText = globalize.translate('LabelDynamicExternalId', fullName); + const labelText = globalize.translate('LabelDynamicExternalId', fullName); html += '
'; html += '
'; - var value = providerIds[idInfo.Key] || ''; + const value = providerIds[idInfo.Key] || ''; html += '
'; html += ''; @@ -448,7 +469,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi html += '
'; } - var elem = context.querySelector('.externalIds', context); + const elem = context.querySelector('.externalIds', context); elem.innerHTML = html; if (externalIds.length) { @@ -464,8 +485,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi function hideElement(selector, context, multiple) { context = context || document; if (typeof selector === 'string') { - - var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)]; + const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)]; Array.prototype.forEach.call(elements, function (el) { if (el) { @@ -483,8 +503,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi function showElement(selector, context, multiple) { context = context || document; if (typeof selector === 'string') { - - var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)]; + const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)]; Array.prototype.forEach.call(elements, function (el) { if (el) { @@ -685,8 +704,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function fillItemInfo(context, item, parentalRatingOptions) { - - var select = context.querySelector('#selectOfficialRating'); + let select = context.querySelector('#selectOfficialRating'); populateRatings(parentalRatingOptions, select, item.OfficialRating); @@ -698,7 +716,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi select.value = item.CustomRating || ''; - var selectStatus = context.querySelector('#selectStatus'); + const selectStatus = context.querySelector('#selectStatus'); populateStatus(selectStatus); selectStatus.value = item.Status || ''; @@ -717,8 +735,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi populateListView(context.querySelector('#listTags'), item.Tags); - var lockData = (item.LockData || false); - var chkLockData = context.querySelector('#chkLockData'); + const lockData = (item.LockData || false); + const chkLockData = context.querySelector('#chkLockData'); chkLockData.checked = lockData; if (chkLockData.checked) { hideElement('.providerSettingsContainer', context); @@ -756,7 +774,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi return a.Name; }).join(';'); - var date; + let date; if (item.DateCreated) { try { @@ -798,7 +816,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi context.querySelector('#txtAirTime').value = item.AirTime || ''; - var placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : ''; + const placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : ''; context.querySelector('#txtPlaceOfBirth').value = placeofBirth; context.querySelector('#txtOriginalAspectRatio').value = item.AspectRatio || ''; @@ -807,8 +825,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi context.querySelector('#selectCountry').value = item.PreferredMetadataCountryCode || ''; if (item.RunTimeTicks) { - - var minutes = item.RunTimeTicks / 600000000; + const minutes = item.RunTimeTicks / 600000000; context.querySelector('#txtSeriesRuntime').value = Math.round(minutes); } else { @@ -817,20 +834,16 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populateRatings(allParentalRatings, select, currentValue) { - - var html = ''; + let html = ''; html += ""; - var ratings = []; - var i; - var length; - var rating; + const ratings = []; + let rating; - var currentValueFound = false; - - for (i = 0, length = allParentalRatings.length; i < length; i++) { + let currentValueFound = false; + for (let i = 0, length = allParentalRatings.length; i < length; i++) { rating = allParentalRatings[i]; ratings.push({ Name: rating.Name, Value: rating.Name }); @@ -844,8 +857,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi ratings.push({ Name: currentValue, Value: currentValue }); } - for (i = 0, length = ratings.length; i < length; i++) { - + for (let i = 0, length = ratings.length; i < length; i++) { rating = ratings[i]; html += "'; @@ -855,7 +867,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populateStatus(select) { - var html = ''; + let html = ''; html += ""; html += "'; @@ -864,7 +876,6 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populateListView(list, items, sortCallback) { - items = items || []; if (typeof (sortCallback) === 'undefined') { items.sort(function (a, b) { @@ -873,8 +884,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } else { items = sortCallback(items); } - var html = ''; - for (var i = 0; i < items.length; i++) { + let html = ''; + for (let i = 0; i < items.length; i++) { html += '
'; html += ''; @@ -896,15 +907,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function populatePeople(context, people) { + let lastType = ''; + let html = ''; - var lastType = ''; - var html = ''; + const elem = context.querySelector('#peopleList'); - var elem = context.querySelector('#peopleList'); - - for (var i = 0, length = people.length; i < length; i++) { - - var person = people[i]; + for (let i = 0, length = people.length; i < length; i++) { + const person = people[i]; html += '
'; @@ -933,14 +942,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi } function getLockedFieldsHtml(fields, currentFields) { - - var html = ''; - for (var i = 0; i < fields.length; i++) { - - var field = fields[i]; - var name = field.name; - var value = field.value || field.name; - var checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : ''; + let html = ''; + for (let i = 0; i < fields.length; i++) { + const field = fields[i]; + const name = field.name; + const value = field.value || field.name; + const checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : ''; html += '